Cloakroom

Disclosure: I built Cloakroom, an open-source tool that masks secrets before AI coding agents see them.

What Cloakroom would and wouldn't have done in October's incidents

An API key is a password that also pays the bill: hold a copy and you can run up charges on someone else's account until they revoke it. In October, developers' keys leaked four different ways in one month.

LiteLLM 1.107.0, a popular AI gateway, shipped an update that copied its users' keys every time Python started; the attacker got in through a master key that had been committed to a public repo. Tensorlake's npm package 0.5.144 carried code that copied developers' keys, used them to spread into their other packages, and planted agent config in repos. Railway, a cloud hosting company, was breached and some stored settings were decrypted. OpenCode's hosted Console exposed the provider keys users had saved in it. I checked which steps Cloakroom touches.

Step by step

stops means Cloakroom, as shipped, prevents the step. reduces means it removes one copy or one path but not the step. none means it is outside what a local agent hook can see.

Incident, stepCloakroom
LiteLLM: master key in an agent config file, committed to a public repo, never revokedreduces (only if the commit went through an agent or Cloakroom's git hook; unknown)
LiteLLM: key used on their agent API, which returned a GitHub tokennone
LiteLLM: stolen token sends repo secrets to a webhook through CInone
LiteLLM: release workflow pointed at a lookalike forknone
LiteLLM: wheels run remote code at every Python startnone
LiteLLM: stealer reads disk, browsers, cloud metadatanone
LiteLLM: encrypted archive sent outnone
LiteLLM: Claude Code puts a GitHub token in a response bodyreduces if it passed through a tool result; none if Claude Code added it to its own API request
Tensorlake: admin account commits the payloadnone
Tensorlake: npm install runs the payloadreduces (narrow: only if the agent runs the install; it masks output, doesn't block)
Tensorlake: reads credential files and .env* filesnone
Tensorlake: plants .claude/settings.json in reposnone
Tensorlake: republishes the victim's packagesnone
Railway: privilege escalation in build infrastructurenone
Railway: encrypted variables pulled, some decryptednone
Railway: search for AI provider key namesnone
OpenCode: legacy system behind Console reachednone
OpenCode: stored provider keys exposednone

The test

I built a git repo with 11 random dummy secrets in the places the stealers look: a .env, a gateway config file, an MCP config, npm, AWS and SSH files, and a script that prints a gho_ token the way gh auth status --show-token does. Claude Code ran the same task twice, plain and with Cloakroom 0.8.0: read the configs, run the script, write a setup file, commit. Then I scanned the model's input, the local session file and git history for the exact dummy values.

WhereWithout CloakroomWith Cloakroom
What the model was given11 of 110 of 11
Session transcript11 of 110 of 11
Git history1 of 11 (the gateway key)0 of 11

The agent's final answer held none in either run. Cloakroom withheld the script's whole output, so the token never reached the model.

Cloakroom refused the agent's write of the gateway key into the setup file. The agent used a placeholder and committed that file alone; the commit check rightly passed it, so it never had a key to stop. Read it as "the key didn't get committed", not as a test of the commit check.

To rerun it (two short runs on your own login): bench/black-october/run.sh

Honest limits

In 0.8.0

Two features shipped today (2026-10-27) in Cloakroom 0.8.0 on PyPI. cloakroom exposure reports which secrets your agents saw. cloakroom scan checks a repo's agent and editor config (.claude/settings.json hooks, .mcp.json, .vscode/tasks.json) for commands that were added or changed, and a git hook runs it after checkout and merge and warns. Both report; neither blocks.

The commands are in the README's command reference.