diff --git a/codex-rs/secrets/src/local.rs b/codex-rs/secrets/src/local.rs index 53fd81340c..83b7027121 100644 --- a/codex-rs/secrets/src/local.rs +++ b/codex-rs/secrets/src/local.rs @@ -2,6 +2,8 @@ use std::collections::BTreeMap; use std::fs; use std::path::PathBuf; use std::sync::Arc; +use std::sync::atomic::Ordering; +use std::sync::atomic::compiler_fence; use age::decrypt; use age::encrypt; @@ -170,9 +172,19 @@ fn generate_passphrase() -> Result { rng.try_fill_bytes(&mut bytes) .context("failed to generate random secrets key")?; let encoded = BASE64_STANDARD.encode(bytes); + wipe_bytes(&mut bytes); Ok(SecretString::from(encoded)) } +fn wipe_bytes(bytes: &mut [u8]) { + for byte in bytes { + // Volatile writes make it much harder for the compiler to elide the wipe. + // SAFETY: `byte` is a valid mutable reference into `bytes`. + unsafe { std::ptr::write_volatile(byte, 0) }; + } + compiler_fence(Ordering::SeqCst); +} + fn encrypt_with_passphrase(plaintext: &[u8], passphrase: &SecretString) -> Result> { let recipient = ScryptRecipient::new(passphrase.clone()); encrypt(&recipient, plaintext).context("failed to encrypt secrets file")