Improper Control of a Resource Through its Lifetime
This weakness occurs when software fails to properly manage a resource—such as memory, a file handle, a database connection, or a temporary credential—from the…
This weakness occurs when software fails to properly manage a resource—such as memory, a file handle, a database connection, or a temporary credential—from the moment it is created until it is safely released. If control is lost or mishandled at any point, an attacker or unintended code path may use, modify, or access that resource in ways the developer never intended, leading to data leaks, privilege escalation, or system instability.
02How It Happens
Resources have a lifecycle: they are allocated, used, and then freed or closed. This weakness arises when code does not enforce consistent control over that lifecycle. Common patterns include: forgetting to release a resource after use (leading to exhaustion or leaks), releasing a resource prematurely while it is still in use elsewhere, failing to validate who or what can access a resource after it is created, or not cleaning up sensitive data before a resource is reused. The root cause is often a mismatch between the code's assumptions about resource ownership and the actual runtime behavior—especially in multi-threaded environments, exception handlers, or complex control flows where cleanup is easy to skip.
03Real-World Impact
Uncontrolled resource lifetimes can lead to denial of service (exhausting file handles, memory, or connection pools), information disclosure (sensitive data left in reused buffers or temporary files), privilege escalation (credentials or tokens not cleared before reuse), or data corruption (concurrent access to a resource without proper synchronization). In web applications, this often manifests as session hijacking, cache poisoning, or account takeover when authentication tokens or session identifiers are not properly invalidated or are reused across different security contexts.
04Vulnerable & Fixed Patterns
Vulnerable pattern
import sqlite3
def fetch_user_data(user_id):
conn = sqlite3.connect(':memory:')
cursor = conn.cursor()
cursor.execute("SELECT * FROM users WHERE id = ?", (user_id,))
result = cursor.fetchone()
# Connection and cursor never closed; resource leak
return result
def process_request(request_data):
temp_file = open('/tmp/request_data.txt', 'w')
temp_file.write(request_data)
# File never closed; handle leak and data persists
return "processed"
Why it's vulnerable: Resources (database connections, file handles) are created but never explicitly closed or cleaned up. In long-running applications, this exhausts available handles and leaves sensitive data in temporary files accessible to other processes.
Fixed pattern
import sqlite3
import tempfile
import os
def fetch_user_data(user_id):
conn = sqlite3.connect(':memory:')
try:
cursor = conn.cursor()
cursor.execute("SELECT * FROM users WHERE id = ?", (user_id,))
result = cursor.fetchone()
return result
finally:
conn.close()
def process_request(request_data):
with tempfile.NamedTemporaryFile(mode='w', delete=True) as temp_file:
temp_file.write(request_data)
temp_file.flush()
# File automatically closed and deleted when exiting the with block
return "processed"
Vulnerable pattern
<?php
function fetch_user_data($user_id) {
$conn = mysqli_connect('localhost', 'user', 'pass', 'db');
$result = mysqli_query($conn, "SELECT * FROM users WHERE id = " . intval($user_id));
$row = mysqli_fetch_assoc($result);
// Connection never closed; resource leak
return $row;
}
function store_session_token($user_id, $token) {
$file = fopen('/tmp/session_' . $user_id . '.txt', 'w');
fwrite($file, $token);
// File never closed; token persists in world-readable temp directory
return true;
}
?>
Why it's vulnerable: Database connections and file handles are opened but never closed, exhausting system resources and leaving sensitive session tokens in temporary files that may be readable by other users or processes.
Fixed pattern
<?php
function fetch_user_data($user_id) {
$conn = mysqli_connect('localhost', 'user', 'pass', 'db');
try {
$stmt = $conn->prepare("SELECT * FROM users WHERE id = ?");
$stmt->bind_param("i", $user_id);
$stmt->execute();
$result = $stmt->get_result();
$row = $result->fetch_assoc();
return $row;
} finally {
$conn->close();
}
}
function store_session_token($user_id, $token) {
// Use secure session storage (e.g., $_SESSION) instead of temp files
session_start();
$_SESSION['user_id'] = $user_id;
$_SESSION['token'] = hash('sha256', $token);
// Session data is managed by PHP; no manual file cleanup needed
return true;
}
?>
05Prevention Checklist
Use language-native resource management constructs: try/finally, context managers (with in Python), or RAII patterns to guarantee cleanup.
Audit all resource allocations (connections, file handles, memory buffers, temporary files) and verify each has a corresponding release or cleanup path.
For sensitive data (credentials, tokens, keys), explicitly zero or overwrite buffers before reuse or release; do not rely on garbage collection alone.
In multi-threaded or async code, use locks or atomic operations to prevent concurrent access to shared resources during their lifecycle.
Implement resource pooling and limits (connection pools, file descriptor limits) to detect and prevent exhaustion attacks.
Test error paths and exception handlers to ensure resources are cleaned up even when code fails or throws.
06Signs You May Already Be Affected
Monitor system logs and resource usage for signs of exhaustion: growing numbers of open file descriptors, unclosed database connections, or memory that does not return to baseline after requests complete. Check temporary directories for stale files containing sensitive data (session tokens, credentials, or user information). Review access logs for unusual patterns of session reuse or token replay across different user accounts or IP addresses.