VNX-244: Secret left in heap memory when it is released
Reports C/C++ free(), delete and realloc() of a buffer named as a password, passphrase, PIN, secret or key with no wipe in the lines before, and Java code that turns a char[] password into an immutable String.
| Field | Value |
|---|---|
| Rule ID | VNX-244 |
| Severity | Medium |
| SARIF level | warning |
| Kind | sast |
| Languages | C, C++, Java |
| CWE | CWE-244 |
| CAPEC | CAPEC-97 |
| ATT&CK | T1557 |
| CWSS vector | CWSS:1.0/TI:M/AP:A/AL:A/IC:N/FC:LT/RP:N/RL:A/AV:I/AS:N/IN:A/SC:A/BI:M/DI:H/EX:M/EC:N/P:C |
| Tags | memory secrets heap-inspection cwe-244 |
| Source | internal/sast/rules/vnx-244.rego |
Overview
Heap memory that held a password or key keeps its contents after it is released. A heap dump, a core file, swap, or the next allocation that receives the same block can read the plaintext. This maps to CWE-244: Improper Clearing of Heap Memory Before Release (‘Heap Inspection’).
What Gets Flagged
- C/C++:
free(),std::free(),g_free(),OPENSSL_free(),deleteanddelete[]of a variable or field whose name ends in password, passwd, pwd, pw, passphrase, pin, secret, session_key, master_key, aes_key, private_key, enc_key, sym_key, key_material, plaintext, cleartext or credential(s), when nomemset/memset_s/explicit_bzero/OPENSSL_cleanse/sodium_memzero/SecureZeroMemorynames it in the 15 lines above. - C/C++:
realloc()of such a buffer, which frees the old block without wiping it. - Java:
new String(field.getPassword()),String.valueOf(console.readPassword(...)), which copy a clearablechar[]into aStringthat can never be cleared.
char *password = read_password_from_tty();
int ok = verify(user, password);
free(password); // flagged
unsigned char *grown = realloc(kb->secret, n); // flagged
String password = new String(passwordField.getPassword()); // flagged
Not flagged: a buffer wiped before release (a plain memset that the optimiser may delete as a dead store is VNX-CWE1037-AUTO’s concern), sodium_free()/OPENSSL_clear_free(), which wipe themselves, ordinary names such as key, token or table, a char[] cleared with Arrays.fill, comments, strings and test code. Garbage-collected languages without a reliable way to clear memory (Go, Python, JavaScript, PHP, Ruby) are not covered.
Remediation
explicit_bzero(password, strlen(password));
free(password);
/* or */
OPENSSL_clear_free(key, key_len);
char[] password = passwordField.getPassword();
try {
auth.login(user, password);
} finally {
Arrays.fill(password, '\0');
}
To grow a secret buffer, allocate a new one, copy, wipe the old one and free it, instead of calling realloc().
References
Suppressing this rule
Put a nosec comment on the line, or on line 1 to cover the whole file. Use the comment marker of the file’s language (#, //, -- or ;):
# nosec vnx-244
// nosec vnx-244
Or record an ignore rule: vulnetix ignore add --rule vnx-244 --reason "...". See Suppressing findings.