Keyclasp Teardown: 15 Tests, 3 Ways It Leaks
Coding agents don't need your API keys in their context — but every practical setup in 2026 still puts them there via .env files and exported shell variables. Keyclasp, which hit the front page of Hacker News today with a fresh 0.2.0-beta.3 release (pushed 20:00 UTC tonight), flips the model: the vault holds the secret, the agent only ever sees the name DEMO_KEY, and the value gets injected into the child process at spawn time. The question that matters isn't whether the demo works. It's what the guardrails actually stop. I installed it, ran the official flow, then threw 15 attacks at it. The answer: three real classes of leak get through, and Keyclasp is honest about all of them.
How the injection actually works
Setup took under two minutes on Node 26:
# vault in a temp dir, unattended mode, dummy credential
export KEYCLASP_HOME=$(mktemp -d)
keyclasp init --machine-only
printf '%s' 'dummy-key-for-keyclasp' | keyclasp set DEMO_KEY --project demo --environment local
keyclasp run --project demo --environment local --env DEMO_KEY -- \
node -e 'console.log("Credential available:", Boolean(process.env.DEMO_KEY))'
# Credential available: true
The agent reads a packaged skill file and is instructed to never call get for plaintext and to inject only named secrets via run --env. One beta wart: npm blocked the install script (install-native-binding.mjs) under allow-scripts policy, and everything still worked — worth knowing before you trust the "hardware custody" story, which is explicitly unavailable in beta anyway. On Linux, machine-only vaults fail closed for get; there is no plaintext retrieval path without a passphrase.
The tests: what it stops
Keyclasp has two defensive layers. Layer one is a command blocklist evaluated before spawn. My first six probes — printenv, env, anything touching sh -c — were rejected pre-execution:
BLOCKED: 'sh' can leak injected secrets by dumping environment variables.
Operator override: keyclasp run --allow-unsafe -- <command...>
Layer two is output scanning. When I let a permitted interpreter (node, python3) print the secret literally, Keyclasp redacted it mid-stream to [KEYCLASP_REDACTED] and then killed the process:
$ keyclasp run ... -- node -e 'console.log("KEY:", process.env.DEMO_KEY)'
KEY: [KEYCLASP_REDACTED]
BLOCKED: command output contained an injected secret; terminated.
That combination — redact, then terminate — is the right call. A raw /proc/$$/environ dump (T7) got the same treatment. The blocklist also correctly refuses to run printenv even when you didn't ask for --env DEMO_KEY on that invocation, which closes the "sibling leak" gap where a leftover export from a previous call gets dumped.
The leaks: three ways past the scanner
Every leak below succeeded against 0.2.0-beta.3 with no overrides:
- Transform exfil (T9).
node -e 'console.log(Buffer.from(process.env.DEMO_KEY).toString("base64"))'printedZHVtbXkta2V5LWZvci1rZXljbGFzcA==. The scanner matches the literal secret, not functions of it. Any encoding — base64, hex, char-codes — walks out the front door. - Per-character mutation (T13). A one-line loop that uppercases one letter produced
dummY-keY-for-keYclasp. Trivially reconstructable by anything reading the output — including the agent's own context, which is the whole thing Keyclasp exists to prevent. - Disk write (T10).
node -e 'fs.writeFileSync("/tmp/leak2.txt", process.env.DEMO_KEY)'— output scanning watches stdout/stderr, not the filesystem. Plaintext lands on disk, 22 bytes, unredacted.
Honorable mentions: the length of the secret leaks freely through .length (T12), and --allow-unsafe disables both layers with a single flag and a one-line warning — a prompt-injected agent's ideal exit.
Verdict: context hygiene, not a security boundary
The README says it outright: "Run only trusted commands... Keyclasp does not sandbox the child." My 15 tests confirm that claim is accurate, not humble. If the child process is malicious — a prompt-injected agent running a poisoned install hook — the secret is gone via base64 in one line. If the child is honest but sloppy, Keyclasp genuinely saves you: it stops printenv accidents, catches literal echoes, and kills the process before a leak finishes streaming. That's the same failure mode as the Claude Code plaintext-credential story — accidental exposure, not theft — and it's the more common one in practice.
So who is this for? Teams where the threat is the agent's context window, not the agent's behavior. Keeping keys out of prompts and transcripts is a real, unsolved problem — transcripts get logged, synced, and fine-tuned on. Keyclasp solves the storage and injection half well and the egress half only against accidents. Treat it as seatbelts, not a cage. And read the warning label, because unlike most tools in this space, it tells you the truth about what it can't do.