CWE-226, Sensitive Information in Resource Not Removed Before Reuse, describes a product that releases a resource such as memory or a file for reuse without clearing, or zeroizing, the information in it before a critical state transition or before another entity can use it.
It matters most in code that handles keys, passwords and personal data: cryptography libraries, network stacks, drivers and anything that reuses buffers.
How it happens
Clearing takes time and resources, so operating systems usually do not erase data when memory is freed or a file is deleted. MITRE adds two more situations. The same process can reuse a buffer, and if the new data is shorter than the old, the tail of the old data remains. Hardware can also be affected when a device moves between power, sleep or debug states, or when execution moves between users or privilege levels.
The observed CVEs show several forms:
- CVE-2019-3733: a cryptography library does not clear heap memory before release.
- CVE-2005-1406: products do not fully clear memory buffers when less data is stored than before.
- CVE-2003-0001: Ethernet NIC drivers do not pad frames with null bytes, leaking information from malformed packets.
- CVE-2003-0291: a router does not clear information from DHCP packets that were used before.
Vulnerable pattern
char *key = malloc(32);
load_key(key);
use_key(key);
free(key); /* key bytes may remain in freed memory */
/* Reused buffer: a short reply leaves the previous reply's tail in place */
send(sock, buf, 256, 0); /* sends 256 bytes, but only 40 were just written */
What an attacker gains
MITRE lists confidentiality: reading application data. The attacker reads leftover data from memory or storage that another party previously used, whether through a later allocation, a malformed packet or a recycled resource.
How to find it
MITRE describes two approaches.
- Manual analysis. Write a known pattern into each sensitive location, trigger the release or the state transition, then read the locations back. If the pattern is still there, the data was not cleared.
- Static analysis. SAST can find some instances by modeling data and control flow in the source or compiled code.
Also review any place a buffer is reused for variable-length data, and any code path that sends a whole buffer instead of the bytes just written.
How to fix it
MITRE's mitigations, both rated highly effective:
- Clear at state transitions. Before a critical state transition, remove or overwrite information not needed in the next state, using fixed patterns such as all zeros or random data.
- Overwrite on release. When releasing, deallocating or deleting a resource, overwrite its data and related metadata with fixed patterns or random data.
Be careful with complex resources. A file may be split into chunks on disk even though its logical positions look contiguous, so clearing it can require special modes or APIs, such as SDelete on Windows, and may not be possible at the application layer.
#include <string.h>
/* Use a call the compiler will not optimize away, for example
explicit_bzero (BSD, glibc) or memset_s (C11 Annex K). */
explicit_bzero(key, 32);
free(key);
An ordinary memset right before free can be removed by an optimizing compiler, which is why a dedicated function is the better choice.
In managed languages you have less control. Prefer short-lived secrets, avoid copying them into immutable strings, and use the platform's secure buffer types where they exist.
Quick check
Does freeing memory erase it?
Usually not. Memory is made available for reuse, and the old contents typically stay until something overwrites them.
Why send only the bytes just written?
Sending a whole buffer can include stale data from earlier use, which is how the NIC driver and DHCP examples leaked.