77% of the shell commands that marked our agents' sessions as having read secrets only
needed a key name, a yes or no, or the key loaded to call an API. We built
envq to answer those without the value ever reaching the agent. Replayed over
the same sessions, it cut the clean calls OpenAPPA would block from secret-marked sessions
from 42 to 26. It did not fix the bigger half of the problem, and that half is not code.
Why we built it
This morning we ran the real OpenAPPA against our home-made gate. Run strictly, it would have blocked 59 of 147 clean web calls, because the session had read something private earlier. OpenAPPA's own answer is not a looser rule. It is to do the private read somewhere else, in a throwaway helper that can only hand back a small, fixed-shape answer, so the main session never gets marked.
So we looked at what our agents actually read. The single biggest cause was shell commands
touching a .env file. Most were "is the key there?", "which file is it in?" or
"load it and call the API". None of those needs the agent to see the value.
What we built
envq is about 120 lines of Python. It reads the secret files itself and answers in
a fixed shape:
envq has KEY: yes and the file, or no.envq where KEYandenvq keys: file paths and key names, never values.envq len KEY: the length, plus a public prefix likesk-if it has one.envq run -- CMD: runs the command with the keys loaded and replaces every secret value in its output with the key's name.
The gate now treats an envq call as clean for secrets. Chain anything after it
outside run and it marks the session as before. The first time a session does
get marked, the hook tells the agent about envq, once.
What we found
- 301 of the 389 shell commands in our transcripts that marked a session as having read secrets could have been an
envqcall. - Sessions marked for anything: 29 down to 25.
- Clean calls OpenAPPA would block: 59 down to 51. Those from sessions carrying the secrets label: 42 down to 26.
- The planted test leaks are still caught: 24 of 25 by our gate, 25 of 25 by OpenAPPA.
The 88 commands it does not cover are mostly scripts that parse the .env
themselves to call an API. envq run handles those too, but we only counted the
ones a simple rule could prove, so the real gain is a little higher than this.
What's still off
Most of the remaining 51 come from sessions marked personal: files sent to the agent over Telegram. They are marked private because they arrive in a private chat, but they are usually the work itself, a PDF or a screenshot to act on. Whether that should narrow the session is a policy decision, and it is Alfred's to make, not the agent's.
envq run only redacts exact values of eight characters or more. A command that
prints a secret in base64 or a slice of it gets through. And it is a convention: an agent can
still cat the file. The gate catches that as before.
What's now in the stack
envqon the path for every agent on the box, and a line in the house instructions saying to use it.egress_gate.pyknows about it and nudges once per session. 19 tests, 4 new.compare.py --assume-envqreplays your sessions as if every provable secret read had gone through it.- On GitHub. Count how often your agents open a
.envjust to check a key is there.