Safeguard
Application Security•

CWE-244 Heap Inspection: Clearing Secrets Before realloc and free

realloc() can leave a copy of a password or key in memory you can no longer reach. CWE-244 explains heap inspection and how to scrub secrets.

Safeguard Security Team
3 min read

CWE-244, known as heap inspection, applies to memory unsafe code in C and C++. Using realloc() to resize a buffer that stores sensitive information can leave that information exposed, because it is not removed from memory.

How it happens

realloc() often has to grow a block by allocating a larger one and copying the old contents across. MITRE explains that this leaves the original block intact but inaccessible to the program. The program can no longer reach it, so it cannot scrub it.

If an attacker can later examine a memory dump, or read memory by other means, the old block may still hold a password or an encryption key.

/* Vulnerable: the old block may keep a copy of the secret */
char *secret = malloc(32);
read_key_into(secret);
secret = realloc(secret, 64);   /* old 32 byte block is unreachable, not wiped */
/* Safer: allocate, copy, wipe the old block, then free it */
char *bigger = malloc(64);
if (bigger == NULL) { /* handle error */ }
memcpy(bigger, secret, 32);
explicit_bzero(secret, 32);     /* a wipe the compiler may not remove */
free(secret);
secret = bigger;

Use whichever guaranteed wipe function your platform provides. A plain memset before free can be removed by an optimizer, which is why dedicated functions exist.

What an attacker gains

The record lists confidentiality: reading memory. It also carries a note to be careful with vfork() and fork() in security sensitive code, since the process state is not cleaned up and will contain traces of data from past use.

MITRE's observed example is CVE-2019-3733, a cryptography library that did not clear heap memory before release. Libraries like that sit under your application, so it pays to know which ones you ship. The free scan at gold.safeguard.sh/scan needs no login and reads up to 100 dependencies without the file leaving your machine.

How to find it

MITRE lists automated static analysis. Search for realloc() on any buffer that holds a password, key, token or similar data.

How to fix it

The record has no mitigation list. From the description:

  • Do not resize secret buffers with realloc(). Allocate the final size up front or use the allocate, copy, wipe, free pattern.
  • Wipe secrets as soon as they are no longer needed.
  • Keep secrets in memory for as short a time as you can.

Wiping secrets in practice

The core idea is that you cannot clean what you cannot reach. When realloc() moves a block, the program holds a pointer to the new block only. The old copy is out of reach, so it cannot be wiped.

That points to a design rule: size buffers that hold secrets once, at the largest size you will need, and never let the allocator move them. If a secret has to grow, make the copy yourself so you control the old block, and wipe it before freeing it.

MITRE's note about fork() and vfork() makes a related point. Process state is not cleaned up automatically, so a child can carry traces of data from earlier use. In code that handles passwords or keys, ask where each secret could be copied, and whether every copy is cleared.

Quick check

Why does realloc leave data behind?

It may copy the contents to a new block and leave the old block untouched. The program no longer has a pointer to it, so it cannot clear it.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.