Zeroize Audit

Automate and integrate Zeroize Audit checks for secure memory handling in code

Zeroize Audit is a community skill for auditing memory zeroization in security-sensitive code, covering secret wiping verification, compiler optimization detection, memory sanitization patterns, and secure cleanup validation for cryptographic key material handling.

What Is This?

Overview

Zeroize Audit provides guidance on verifying that security-sensitive data like cryptographic keys, passwords, and tokens are properly wiped from memory after use. It covers secret wiping verification that confirms buffers are zeroed before deallocation, compiler optimization detection that identifies dead store elimination of zeroization code, memory sanitization patterns using volatile pointers and platform secure-zero functions, secure cleanup validation that tests whether data persists after cleanup, and language-specific guidance for Rust zeroize crate, C SecureZeroMemory, and explicit_bzero. The skill helps security engineers prevent data leakage through residual memory.

Who Should Use This

This skill serves security engineers auditing cryptographic implementations, developers handling sensitive credentials in memory, and teams building applications that must comply with security standards requiring secret zeroization.

Why Use It?

Problems It Solves

Compilers optimize away memset calls used for zeroization when they detect the buffer is not read afterward, leaving secrets in memory. Standard memory deallocation does not clear buffer contents allowing sensitive data to persist in freed memory pages. Code review alone cannot determine whether zeroization calls survive compiler optimization at different build configurations. Memory dumps, core files, and swap partitions can expose secrets that were not properly cleared.

Core Highlights

Wipe verifier confirms sensitive buffers are zeroed before deallocation. Optimization detector identifies compiler-removed zeroization dead stores. Pattern library provides platform-specific secure clearing functions. Cleanup validator tests whether secrets persist after cleanup execution.

How to Use It?

Basic Usage

// Rust zeroize usage
use zeroize::Zeroize;

struct SecretKey {
    key: Vec<u8>,
    iv: [u8; 16],
}

impl Drop for SecretKey {
    fn drop(&mut self) {
        self.key.zeroize();
        self.iv.zeroize();
    }
}

fn process_key() {
    let mut secret =
        SecretKey {
            key: vec![
                0x42; 32],
            iv: [0x01; 16],
        };
    // Use the key
    encrypt(&secret);
    // Automatic zeroize
    // on drop
}

// Derive Zeroize
#[derive(Zeroize)]
#[zeroize(drop)]
struct Credentials {
    username: String,
    password: String,
}

Real-World Examples

/* C secure zeroization */
#include <string.h>
#include <stdlib.h>

/* BAD: compiler may
   optimize this away */
void bad_cleanup(
    char *key, size_t len
) {
    memset(key, 0, len);
    free(key);
}

/* GOOD: platform secure
   zero function */
#ifdef _WIN32
#include <windows.h>
void secure_cleanup(
    char *key, size_t len
) {
    SecureZeroMemory(
        key, len);
    free(key);
}
#else
void secure_cleanup(
    char *key, size_t len
) {
    explicit_bzero(
        key, len);
    free(key);
}
#endif

/* GOOD: volatile pointer
   prevents optimization */
void volatile_zero(
    void *ptr, size_t len
) {
    volatile char *p =
        (volatile char *)
            ptr;
    while (len--) {
        *p++ = 0;
    }
}

Advanced Tips

Inspect compiled binary output with objdump or disassembler tools to verify zeroization calls are not eliminated at different optimization levels. Use address sanitizer memory tracking to verify buffer contents are actually cleared during test execution. Implement zeroization in Drop or destructor implementations to ensure cleanup runs even when errors cause early function exits.

When to Use It?

Use Cases

Audit a cryptographic library to verify all key material is zeroized when key objects are destroyed. Review authentication code to confirm passwords and tokens are cleared from memory after validation. Validate that a Rust crate properly derives Zeroize on all structs containing sensitive fields.

Related Topics

Memory security, cryptographic key management, secure coding, compiler optimization, zeroize crate, and sensitive data handling.

Important Notes

Requirements

Understanding of compiler optimization behavior for identifying dead store elimination of zeroization calls. Platform-specific secure memory clearing functions for the target operating system and language environment. Debugging or binary analysis tools for verifying that zeroization instructions survive compilation.

Usage Recommendations

Do: use platform-provided secure zeroization functions like explicit_bzero or SecureZeroMemory that are guaranteed not to be optimized away. Implement zeroization in destructors or Drop traits so cleanup happens automatically when objects go out of scope. Verify zeroization at multiple compiler optimization levels since behavior can differ between debug and release builds.

Don't: rely on plain memset for zeroization since compilers routinely optimize it away as a dead store. Assume that freeing memory clears its contents since deallocated pages retain their data until reused. Skip zeroization for temporary buffers that hold derived keys or intermediate cryptographic values.

Limitations

Verifying zeroization requires binary-level analysis since source code inspection cannot confirm compiler optimization behavior. Memory may be copied to swap space or crash dumps before zeroization occurs creating exposure windows. Garbage-collected languages offer limited control over when objects are deallocated making deterministic zeroization more difficult to guarantee.