What's actually in your agent's context window: secrets you didn't know were there
You probably have a mental model of what your coding agent sees: the files in the repo, the output of the commands it runs. That model is too small. The context window is assembled from everything the agent reads, and agents read aggressively because that is how they are useful. Most of the secrets that end up in a context window were never meant to be there. They were ambient. They sat in files the agent opened for unrelated reasons. Here is what is actually in there.
The .env file you forgot
The most common leak is the least surprising. .env files, docker-compose
files with environment blocks, CI configs, and dotfiles sit in repos and
home directories, and agents open them while exploring a project. A single
read of .env puts every key in the project into context — including keys
for services the agent never needed.
Git history and its copies
Old credentials live in git. A key committed two years ago and rotated last month still exists in history, in reflog entries, in stashes, and in every clone. Agents that inspect history — for blame, for archaeology, for debugging — pull those old values forward into a fresh session. Rotating a key does not remove it from git; nothing short of history rewriting does.
Test fixtures and example configs
Repos are full of plausible-looking secrets: test credentials, sample configs, mocks, golden files. Some are real values that were copied into fixtures and never cleaned up. Some are realistic enough to pass a human review. Entropy-based detection catches both — a high-entropy string is a high-entropy string whether it is a production key or a well-crafted fake.
Encoded variants
Secrets rarely appear in logs in plaintext form. They appear base64-encoded, URL-encoded, percent-encoded, or split across lines. A scanner that only matches the literal key misses all of them. Real detection works in layers: a keyword pre-filter narrows the candidate set, regex rules match known patterns, and Shannon entropy catches strings that match no pattern at all. A minimum length threshold keeps the noise down, because short strings are rarely worth flagging.
Why it matters
Secrets in context are not just visible to you. Context is sent to a model API operated by someone else, persisted in session transcripts, and replayed in summaries. And once a secret is in context, a prompt-injected instruction — from a README, a webpage, a fetched diff — can request it, and the agent may comply. The blast radius of one leaked token is the whole context window, not one line.
What to do about it
Two complementary moves. Before sessions, keep secrets out of the files
agents read: stop exporting them into shell environments, inject them at
subprocess spawn instead, and filter outbound traffic at the egress layer.
After sessions, assume something leaked and scrub retroactively. Retroactive
scrubbing is two-layer redaction: known values plus pattern matches, with a
dry run by default and a backup taken before --apply. In SQLite-backed
session stores, scrubbing must also rebuild the full-text index and vacuum
the file — deleting rows alone leaves values recoverable on disk.
The tooling that does this without inventing a new vault exists: trustless reads your existing pass or Bitwarden store, and its scrub commands handle the two-layer redaction and index rebuild described above, with the details in the commands documentation.
The uncomfortable question is not whether your context window has ever contained a secret. It is whether you could prove it hasn’t — could you?