feat(vault-agent): mlock the user keys (no swap exposure)#32
Merged
Conversation
Completes the agent memory-hygiene hardening (after core dumps + ptrace): the unwrapped user keys are now locked into RAM so they can't be paged to a swap file. - sealed.rs: a `SealedKey` newtype wrapping the user key. It boxes the bytes (stable heap address that survives `Vault` moves) and best-effort `mlock`s the page via the safe `region` crate — surgical (only the key pages, never the whole process → no RLIMIT_MEMLOCK/OOM risk), keeping the crate's forbid(unsafe_code). On drop it zeroizes while still locked, then munlocks. Stores `locked: bool` (not the LockGuard) so it stays Send (Vault lives in Arc<Mutex<…>>). - state.rs/unlock.rs: `Vault.user_enc`/`user_mac` become `SealedKey`. `SealedKey: Deref<Target=[u8;32]>`, so the ~60 encrypt/decrypt call sites and the SessionBlob copy-out are unchanged; only the construction sites wrap the keys. `vault_from_user_key` now borrows the keys. - docs: CHANGELOG, README hardening line, plus the existing test stubs. The persona's memory-hygiene ask (core dumps + ptrace + no-swap) is now complete. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Completes the agent's memory-hygiene hardening (after core dumps + ptrace in PR #31): the unwrapped user keys (
user_enc/user_mac) are nowmlocked into RAM so they can't be paged to a swap file. This finishes the "Security-aware power user" persona's ask (no swap exposure, mlocked keys).How
crates/vault-agent/src/sealed.rs— a newSealedKeynewtype wrapping the key:Vault/SealedKeymoves (so the lock taken at construction stays valid);mlocks just that page via the saferegioncrate — surgical (only the key pages, never the whole process), so it's always withinRLIMIT_MEMLOCKand can't OOM the tokio/rustls allocator (unlikemlockall(MCL_FUTURE)). Keeps#![forbid(unsafe_code)];Drop: zeroizes while the page is still locked, thenmunlocks;locked: bool(not theLockGuard) soSealedKey: Send— required sinceVaultlives inArc<Mutex<…>>across awaits.state.rs/unlock.rs—Vault.user_enc/user_macbecomeSealedKey. SinceSealedKey: Deref<Target=[u8; 32]>, the ~60&v.user_encencrypt/decrypt sites and theSessionBlobcopy-out are unchanged; only the construction sites wrap the keys, andvault_from_user_keynow borrows them.Tests
sealed.rs:Derefreturns the key bytes (the path every call site relies on) andDebugdoesn't leak bytes. The whole existingvault-agentsuite (unlock round-trips, add/edit, pin, resume) stays green throughSealedKey'sDeref— proof the newtype is transparent.Verification
fmt --check, fresh-isolatedclippy --all-features -D warnings,cargo test --workspace --all-targets,cargo deny check(region MIT), both headless builds (the dep is non-optional) — all green.Manual on a normal kernel: unlock the agent, then
grep VmLck /proc/$(pgrep -n vault-agent)/status→ non-zero locked memory.Out of scope (still pending for the v0.1 tag)
The ≥24h fuzz soak, a live PQC handshake test, and the §11.2 two-week daily-driver attestation — then a slice cuts
v0.1.0.🤖 Generated with Claude Code