Missing Initialization of Resource
Description
Missing Initialization of Resource is a vulnerability where software fails to properly initialize a critical resource before it is used. Many resources require explicit initialization to function correctly—without it, they may contain unpredictable data from previous operations, invalid default values, or garbage data. This vulnerability differs from CWE-908 (Use of Uninitialized Resource) in that it focuses on the failure to perform initialization, while CWE-908 focuses on the subsequent use of the uninitialized resource.
Risk
Resources that are not properly initialized can lead to serious security issues. Uninitialized memory may contain sensitive data from previous operations, leading to information disclosure. Variables with missing initialization may have unpredictable values that affect program logic or security decisions. In access control contexts, missing initialization may result in default values that grant excessive privileges. Buffer operations on uninitialized memory can cause crashes or enable exploitation. The unpredictable nature of uninitialized data makes debugging difficult and can create intermittent, hard-to-reproduce security issues.
Solution
Ensure all resources are properly initialized before use. Define initialization procedures for all custom data types and structures. Use constructors or initialization functions that set all fields to known safe values. In languages without automatic initialization, use memset() or calloc() for memory allocation. Implement coding standards that require explicit initialization. Enable compiler warnings for missing initialization. Use static analysis tools to detect missing initialization. For security-critical code, initialize all variables at declaration time. Consider using languages with mandatory initialization requirements.
Common Consequences
| Impact | Details |
|---|---|
| Confidentiality | Scope: Confidentiality Read Application Data - Uninitialized resources may expose sensitive information when reused without clearing original contents. |
| Availability | Scope: Availability DoS: Crash/Exit/Restart - Missing initialization can cause unexpected program flow leading to crashes or denial of service. |
| Integrity | Scope: Integrity Alter Execution Logic - Uninitialized values may affect program logic in unpredictable ways. |
Example Code
Vulnerable Code
// Vulnerable: Missing initialization of character array
#include <stdio.h>
#include <string.h>
void vulnerable_build_path(char *filename) {
char path[256]; // Missing initialization
// Vulnerable: strcat assumes path is empty string
// but path contains garbage that may include sensitive data
strcat(path, "/home/user/");
strcat(path, filename);
printf("Path: %s\n", path);
}
// Attack: Sensitive data from previous stack usage may leak
// Vulnerable: Boolean initialized to wrong value prevents setup
public class VulnerableConfig {
private boolean initialized = true; // Wrong! Should be false
private String connectionString;
private int maxConnections;
public void setupIfNeeded() {
if (!initialized) {
// This code never runs because initialized == true
connectionString = loadFromConfig("database.url");
maxConnections = loadFromConfig("max.connections");
initialized = true;
}
}
public String getConnectionString() {
setupIfNeeded();
return connectionString; // Returns null!
}
}
// Vulnerable: Structure not initialized
typedef struct {
int user_id;
int privilege_level;
char username[64];
int permissions[10];
} UserSession;
UserSession* vulnerable_create_session() {
UserSession *session = malloc(sizeof(UserSession));
// Missing: No initialization of structure
// All fields contain garbage values
// Only setting username
strcpy(session->username, "guest");
return session; // privilege_level may be garbage (possibly 0 = admin)
}
# Vulnerable: Resource conditionally initialized
class VulnerableDataProcessor:
def __init__(self, config):
# Missing: self.cache not always initialized
if config.get('enable_cache'):
self.cache = {}
def process(self, key, data):
# Vulnerable: cache may not exist
if key in self.cache: # AttributeError if cache not initialized
return self.cache[key]
result = expensive_computation(data)
# Vulnerable: Will fail if cache doesn't exist
self.cache[key] = result
return result
// Vulnerable: File permission structure not initialized
#include <sys/stat.h>
int vulnerable_set_permissions(const char *path) {
struct stat file_stat;
mode_t mode; // Missing initialization
// Only set some permission bits
if (is_private_file(path)) {
mode |= S_IRUSR | S_IWUSR; // mode already has garbage!
}
// Garbage bits may include S_ISUID, S_ISGID, or world permissions
return chmod(path, mode);
}
// Vulnerable: Object with uninitialized members
class VulnerableBuffer {
char *data;
size_t size;
size_t capacity;
public:
VulnerableBuffer() {
// Missing: No initialization of members
// data, size, capacity all contain garbage
}
void append(const char *str) {
size_t len = strlen(str);
// Uses uninitialized capacity for comparison
if (size + len > capacity) {
// Uses uninitialized data pointer
data = (char*)realloc(data, capacity * 2); // Undefined behavior
}
memcpy(data + size, str, len); // Uses uninitialized size
size += len;
}
};
Fixed Code
// Fixed: Proper initialization of character array
#include <stdio.h>
#include <string.h>
void fixed_build_path(char *filename) {
char path[256];
// Fixed: Initialize to empty string
path[0] = '\0';
// Or: memset(path, 0, sizeof(path));
// Now strcat works correctly
strcat(path, "/home/user/");
// Also validate to prevent overflow
if (strlen(path) + strlen(filename) < sizeof(path)) {
strcat(path, filename);
}
printf("Path: %s\n", path);
}
// Fixed: Proper initialization flag
public class FixedConfig {
private boolean initialized = false; // Fixed: Correct initial value
private String connectionString;
private int maxConnections;
public synchronized void setupIfNeeded() {
if (!initialized) {
connectionString = loadFromConfig("database.url");
maxConnections = loadFromConfig("max.connections");
// Validate loaded values
if (connectionString == null) {
throw new ConfigurationException("Missing database.url");
}
initialized = true;
}
}
public String getConnectionString() {
setupIfNeeded();
return connectionString; // Now properly initialized
}
}
// Fixed: Complete structure initialization
typedef struct {
int user_id;
int privilege_level;
char username[64];
int permissions[10];
} UserSession;
UserSession* fixed_create_session() {
// Fixed: Use calloc for zero-initialization
UserSession *session = calloc(1, sizeof(UserSession));
if (session == NULL) {
return NULL;
}
// Or with explicit initialization:
// memset(session, 0, sizeof(UserSession));
// Set specific fields to known values
session->user_id = INVALID_USER_ID;
session->privilege_level = PRIVILEGE_NONE;
strcpy(session->username, "guest");
// permissions array already zero (no permissions) from calloc
return session;
}
// Better: Designated initializer (C99+)
UserSession create_session_inline() {
UserSession session = {
.user_id = INVALID_USER_ID,
.privilege_level = PRIVILEGE_NONE,
.username = "guest",
.permissions = {0}
};
return session;
}
# Fixed: Ensure all resources initialized
class FixedDataProcessor:
def __init__(self, config):
# Fixed: Always initialize cache
self.cache = {} if config.get('enable_cache') else None
self.cache_enabled = config.get('enable_cache', False)
def process(self, key, data):
# Fixed: Check if caching is enabled
if self.cache_enabled and self.cache is not None:
if key in self.cache:
return self.cache[key]
result = expensive_computation(data)
if self.cache_enabled and self.cache is not None:
self.cache[key] = result
return result
# Alternative: Initialize in __init__ unconditionally
class BetterDataProcessor:
def __init__(self, config):
self.cache = {} # Always initialize
self.use_cache = config.get('enable_cache', False)
def process(self, key, data):
if self.use_cache and key in self.cache:
return self.cache[key]
result = expensive_computation(data)
if self.use_cache:
self.cache[key] = result
return result
// Fixed: Proper permission initialization
#include <sys/stat.h>
int fixed_set_permissions(const char *path) {
struct stat file_stat;
// Fixed: Initialize mode to known safe value
mode_t mode = 0; // No permissions initially
if (is_private_file(path)) {
mode = S_IRUSR | S_IWUSR; // Only owner read/write
} else {
mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; // Owner write, all read
}
return chmod(path, mode);
}
// Fixed: Proper member initialization
class FixedBuffer {
char *data;
size_t size;
size_t capacity;
public:
// Fixed: Use initializer list
FixedBuffer() : data(nullptr), size(0), capacity(0) {
}
// Fixed: Initialize with specified capacity
explicit FixedBuffer(size_t initial_capacity)
: data(nullptr), size(0), capacity(initial_capacity) {
if (initial_capacity > 0) {
data = new char[initial_capacity];
}
}
~FixedBuffer() {
delete[] data;
}
void append(const char *str) {
size_t len = strlen(str);
if (size + len >= capacity) {
size_t new_capacity = (capacity == 0) ? 64 : capacity * 2;
while (new_capacity < size + len + 1) {
new_capacity *= 2;
}
char *new_data = new char[new_capacity];
if (data != nullptr) {
memcpy(new_data, data, size);
delete[] data;
}
data = new_data;
capacity = new_capacity;
}
memcpy(data + size, str, len);
size += len;
data[size] = '\0';
}
};
CVE Examples
- CVE-2020-20739: Variable was set only under certain conditions, leading to data leakage when condition failed.
- CVE-2005-1036: Improperly initialized I/O permission bitmap allowed bypassing of access restrictions.
Related CWEs
- CWE-665: Improper Initialization (parent)
- CWE-456: Missing Initialization of a Variable (child)
- CWE-908: Use of Uninitialized Resource (can follow)
- CWE-1271: Uninitialized Value on Reset for Registers (child - hardware specific)
References
- MITRE Corporation. "CWE-909: Missing Initialization of Resource." https://cwe.mitre.org/data/definitions/909.html
- CERT C Secure Coding Standard. "EXP33-C. Do not read uninitialized memory."
- CERT C Secure Coding Standard. "DCL30-C. Declare objects with appropriate storage durations."