Security
The never-reveal invariant.
ClauLock's central guarantee is structural, not probabilistic: the Claude model never receives the plaintext value of a stored secret. The MCP surface is shaped so that no tool, under any input, returns a raw value. Enforcement happens at the socket, not in a prompt.
"Probabilistic" means a model could be talked into leaking under the right adversarial prompt. "Structural" means the leak path doesn't exist — there's no API call that returns a plaintext value to the model, regardless of how the model is prompted.
What ClauLock protects against
- Transcript leaks.
Shell commands referencing
{{NAME}}are rewritten at the PreToolUse hook to run underclsec-exec; the placeholder stays in the transcript and the value is substituted atfork/exec. - Exfil via MCP. The MCP server
runs under role
Mcp, which the daemon blocks from callingMethod::Resolve. A compromised MCP binary still cannot ask for a value. - Memory scraping. DEKs and the
KEK live in
mlocked pages and are zeroed on drop. Anti-debugger hardening (PT_DENY_ATTACH) is on the upcoming roadmap; for now ClauLock assumes an uncompromised user session. - Socket spoofing. The daemon
binds a
0600Unix socket in the user's runtime directory and verifies callers viaSO_PEERCRED(Linux) /LOCAL_PEERPID(macOS), matching the peer binary against an allowlist. - Record-swap attacks. Each record is encrypted with the record id as AAD, so an attacker with write access to the vault cannot splice a ciphertext under a different name.
What ClauLock does not protect against
- A fully compromised endpoint. Root-level malware with access to your kernel, your process memory, or your keyboard can always win. ClauLock raises the cost, not to infinity.
- User-initiated leaks. If you ask Claude to "print my GitHub token," ClauLock will not hand it over — but if you paste it into chat yourself, the transcript will contain it. We can't protect you from you.
- Remote services misusing secrets.
Once
curlsends your token to GitHub, GitHub has it. ClauLock is not a policy engine for upstream APIs. - Swap / hibernation leaks.
mlockprevents paging of the daemon's sensitive pages; we still recommend encrypted swap.
Cryptographic details
passphrase (macOS Keychain / freedesktop secret-service)
↓ Argon2id (m = 256 MiB, t = 3, p = 4)
KEK (32 bytes)
↓ XChaCha20-Poly1305 wrap
DEK₁ (32 bytes, random, per record)
↓ XChaCha20-Poly1305 (AAD = record_id)
ciphertext₁ - AEAD: XChaCha20-Poly1305, 24-byte random nonces, record id bound as AAD.
- KDF: Argon2id with the OWASP parameters above; tuning knobs exposed for enterprise builds.
- Rotation: rotating the
passphrase re-wraps DEKs but does not re-encrypt every secret.
Rotating a secret generates a fresh DEK and preserves
idandcreated_at. - Vault format: append-only, atomically swapped on write, portable across machines when paired with the passphrase.
Roles and access control
| Role | Binary | Can call Resolve? |
|---|---|---|
Cli | clsec, clsec-exec | Yes |
Mcp | clsec-mcp | No — blocked at the daemon |
Ui | Companion app (planned) | Yes, with biometric approval |
The Companion UI exception
The Companion UI is the only
ClauLock surface that can show a secret's plaintext value, and
only after a fresh Touch ID prompt for that specific reveal.
This is a deliberate exception that respects the invariant: the
Claude model still cannot pull the value through any path —
the daemon's role gate denies Method::Reveal
for every caller except CallerRole::Ui,
and denies Method::Resolve for
Mcp and Ui.
- Ephemeral display. The value renders in the UI for 15 seconds and auto-hides. No shell history, no scrollback, no pager. Clipboard copies auto-clear after 20 seconds.
- Per-action biometric.
Vault-unlocked-an-hour-ago is not sufficient. Every reveal
re-prompts Touch ID. Linux uses
polkit(planned). Windows Hello support tracks the next Windows release. - Attributable. Every
reveal lands in the audit log with
tool=reveal, outcome=ok|denied— visible viaclsec auditor in the UI's own audit timeline. - Out of scope: a compromised local user session. If an attacker controls the logged-in account, they can pass Touch ID with the user's finger or shoulder-surf the 15-second window. ClauLock is not a Yubikey replacement; it's an agent-context boundary. See docs/ui-reveal.md for the full trust-boundary diagram and protocol details.
Audit log
Every Add,
Resolve,
Rotate, and
Delete is recorded with timestamp,
caller PID, caller binary path, and result. Read it from the CLI:
clsec audit --limit 50 Reporting a vulnerability
Email [email protected] — do not open a public issue. We acknowledge within 48 hours and target a fix within 30 days for high-severity findings. Full policy and bounty tiers in SECURITY.md.