Wipe secrets with an optimisation barrier¶
- Status: accepted
- Date: 2026-09-06
Context and Problem Statement¶
SecretBuffer holds signing-key material and must guarantee the memory is
actually cleared on destruction. A plain fill over memory that is never read
again is a dead store, and a compiler is entitled to remove it (CWE-14,
"Compiler Removal of Code to Clear Buffers").
Considered Options¶
sodium_munlock, which zeroises and unpins and is an optimisation barrierstd::ranges::fill(the prior approach)
Decision Outcome¶
Chosen option: "sodium_munlock", because it is a barrier the compiler cannot
elide, unlike the prior std::ranges::fill dead store.
Negative Consequences¶
src/coremust link libsodium, which is otherwise confined by ADR-0014.src/core/secret_buffer.cppis one of the named exceptions inscripts/reject-unsafe.shfor exactly this reason.- Custom move-constructor and move-assignment are mandatory: they must transfer the mlock and wipe the source, or the secret is duplicated or left pinned in a moved-from object. A defaulted move would silently break this.