CWE-316: Cleartext Storage of Sensitive Information in Memory
Overview
Storing sensitive data (passwords, keys, tokens) in memory as cleartext exposes it to memory dumps, core dumps, swap files, hibernation files, debuggers, and memory disclosure vulnerabilities. Sensitive data should have the shortest practical lifetime, should be cleared from mutable buffers when possible, and should be kept out of dumps and swap for high-risk processes.
Relationship to Other CWEs
- CWE-316 (this page) - Sensitive data held as cleartext in process memory, where memory dumps, core dumps, swap and hibernation files, and debuggers can read it.
- CWE-312 (Cleartext Storage of Sensitive Information) - The broader parent category, covering cleartext storage in any medium rather than only in memory.
- CWE-313 (Cleartext Storage in a File or on Disk) - A sibling under CWE-312, for data written to disk: config files, database files, logs, and backups.
OWASP Classification
A06:2025 - Insecure Design
Risk
Medium-High: Cleartext in memory enables data theft via crash dumps, debugger attachment, memory disclosure bugs (Heartbleed), swap file analysis, hibernation file reading, memory scraping malware, and cold boot attacks on RAM.
Remediation Steps
Core Principle: Minimize how long sensitive data exists in cleartext memory, avoid unnecessary copies, and use platform protections where they actually apply.
Locate cleartext sensitive data in memory
- Start from the file, line and code pattern the finding points at
- Identify what sensitive data is held there: passwords, cryptographic keys, tokens, PII
- Trace its lifetime: where it is loaded into memory, how long it persists, and when (if ever) it is cleared
- Work out the exposure: can it be swapped to disk, captured in a crash dump, or read by an attached debugger
Clear sensitive data after use (Primary Defense)
- Overwrite mutable buffers holding passwords or keys as soon as you are done with them, wherever the runtime gives you one -
Arrays.fill(password, '\0')in Java - Use platform-specific secret containers carefully: These can reduce exposure, but they often have platform limits and still require conversion to plaintext at the point of use
- Prefer clearable arrays or buffers over strings where the input path allows it: Strings are immutable and cannot be overwritten in place
- Use explicit_bzero() or memset_s() in C and C++: A plain memset can be optimized away; these cannot
What clearing does and does not buy
Clearing is best-effort:
- A moving collector has already made copies. The JVM, the CLR and V8 all relocate live objects during collection, so one logical secret can exist at several addresses the program never held a reference to. Zeroing the array you can reach does nothing about those.
- The clear only covers the buffer it is given. Any conversion on the way to the consuming API - to a
String, to a JSON body, to a log record - produces a copy the wipe cannot reach. - The compiler may delete the wipe in unmanaged code. A plain
memsetover a buffer the compiler can see is dead is removable under the as-if rule, which is why C and C++ needexplicit_bzero()ormemset_s()rather thanmemset().
What clearing does buy is a shorter window: an attacker holding a dump has to have taken it while the secret was resident. Decide whether that narrower window is what you need before restructuring code around it - for most applications, controlling who can take a dump matters more than what the process does with its buffers.
Prevent memory swapping to disk
- Use
mlock()to lock pages in RAM (Linux): Reduces the chance that selected pages are swapped to disk; check return values and account for process limits - Use
VirtualLock()on Windows: Locks selected pages, subject to working-set and privilege constraints - Mark pages as non-swappable: Use OS-specific APIs on the buffers that actually hold the secret; copies elsewhere remain swappable
- Disable swap for critical processes: Justifiable in high-security deployments, but not a substitute for clearing secrets and controlling crash dumps
Use secure memory abstractions
- Use OS or library protected-memory APIs where available: For example, libsodium secure memory can add guard pages, locking, and explicit zeroing
- Use framework secret containers only when their limitations fit your platform: Microsoft recommends against
SecureStringfor new .NET development on every platform, not only outside Windows. The encryption is Windows-only, and even where it works every use has to convert the value back to plain text - Keep long-lived secrets in a vault, an HSM or a cloud KMS, or issue short-lived tokens instead, rather than letting the application manage plaintext keys
Minimize exposure time in memory
- Load a secret just before use and clear it immediately after
- Do not log passwords, keys or tokens, even at debug level
- Do not concatenate secrets into strings: each concatenation creates an immutable copy that cannot be cleared
Test the memory protection fix
Re-scanning proves the pattern the tool matched is gone, not that the secret left memory, so assert the outcomes directly:
- The buffer the fix zeroes reads back as all zeros immediately after the operation, on the exception path as well as the success path
- A dump taken after the operation completes does not contain the test secret. A dump taken during it still will, and should - that is the window the fix shortens rather than closes, so do not treat a hit there as the fix having failed
- Every legitimate flow that touched the secret still works: login succeeds, the token verifies, the ciphertext decrypts. Refactoring around clearable buffers is where a secret gets cleared one call too early, and the symptom is a failure only the accept case shows
mlock/VirtualLockreturn zero, and the application degrades rather than aborting when they do not -RLIMIT_MEMLOCKis small by default and a container may not grantCAP_IPC_LOCK- Non-ASCII passwords authenticate. A
char-to-byteconversion that truncates is invisible to every other test
Common Vulnerable Patterns
- Holding passwords or keys in immutable strings, which cannot be overwritten
- Not clearing a char[] or byte buffer after use
- Logging sensitive data
- Not locking memory pages
Language-Specific Guidance
For detailed implementation guidance and code examples in your programming language:
- Python - Using
bytearray,mlock, context managers, and secure framework patterns - Java - Using
char[],Arrays.fill(),AutoCloseable, and Spring Security trade-offs - JavaScript/Node.js - Using
Buffer,fill(0),crypto.timingSafeEqual(), and Express/Next.js patterns - C# - Using
Array.Clear(),SafeHandleover unmanaged memory, and whySecureStringis not the answer on current .NET