1 · How secrets escape
The Secret Leak Field Manual · 7 min read
Question this chapter answers: Once a key leaves your source code, where does it actually go?
The map this book keeps returning to
The repository is the one surface with mature, widely deployed scanning. Repo scanners exist, teams run them, dashboards stay green — and keys still leak, because the repository is only one of eight surfaces a secret touches on its way from "someone pasted it somewhere" to "someone else can read it."
This chapter is the surface map. Every later chapter refers back to it.
| # | Surface | How a secret gets there | Who can read it | How it is usually found |
|---|---|---|---|---|
| 1 | Source and git history | Hardcoded during debugging; committed in .env; added by an agent or autocomplete | Everyone with repo access; everyone on earth if the repo is public, forever in history | Secret scanning, code review |
| 2 | Build logs and CI output | A command echoes environment variables; a test prints config; a stack trace carries a connection string | Everyone who can see job logs — often a wider group than repo access, sometimes the public internet for open source | Reading your own logs |
| 3 | CI artifacts and caches | Build artifacts embed env values at compile time; caches and uploaded bundles carry them along | Everyone with artifact access, which is routinely broader than source access | Unpacking what you ship |
| 4 | Browser bundles and HTML | Build-time substitution writes VITE_-style variables into JavaScript; streamed server data hands secrets to client components; published source maps restore original code | Every visitor's browser, plus every crawler | Scanning the deployed app |
| 5 | Error trackers and log aggregators | An exception message includes the failing URL with credentials embedded; a debug payload logs the whole config object | Your team, your vendor, and anyone who gains access to either | Searching the tracker |
| 6 | Mobile and native binaries | The same substitution that inlines values into web bundles inlines them into compiled packages | Anyone who unpacks the binary | Static analysis of shipped binaries |
| 7 | Collaboration surfaces | Tickets, chat threads, screenshots, shared docs, paste sites | Everyone in the workspace; paste sites make it the world | Search inside the tools |
| 8 | AI-assistant loops | Keys pasted into prompts as context; agents echoing keys into generated files; agents making real calls with real keys to prove things work; tool configurations holding provider keys | Whoever can read the prompt history, session data, or the artifacts the agent produced | Reviewing what the assistant produced |
Two properties of this map drive everything else in the book.
First: surfaces multiply silently. One key, one careless moment, becomes copies on four or five surfaces without anyone deciding anything. The commit lands in source (surface 1), CI prints a variable while building (2), the built bundle inlines the value at compile time (4), and an error tracker captures it the first time something fails (5). Cleaning one surface does nothing about the others.
Second: discovery does not mean containment. Finding a key on surface 4 tells you nothing yet about surfaces 1 through 7. Blast-radius work (Chapter 3) and rotation playbooks (Chapter 6) exist because the leak is almost never a single location.
Why "clean repo" is not "clean build"
The build is the step teams forget, and it is the step that decides what strangers see. Frameworks substitute environment variables into bundles at build time: a value prefixed for public exposure gets written literally into the JavaScript that ships. If a secret-bearing variable wears a public prefix — renamed to silence a build error, or set by a template — the substitution publishes it. The repository never contained the literal; the deployed app does.
This is why repo scanning and deployed-app scanning answer different questions. A repo scan asks: did a secret enter version control? A deployed scan asks: what does a visitor's browser actually download? Both matter. Neither substitutes for the other. The pipeline chapter (Chapter 7) places each check where its coverage is real.
Published source maps extend the problem backward in time: they reconstruct original source files, comments and all, from the minified output you shipped. Teams disable them in production or gate them behind authentication precisely because minification was hiding literals, not encrypting them.
The two incidents worth reading
When a build pipeline itself is compromised, every secret flowing through it is exposed, no matter how careful any individual team was. In 2021, Codecov's Bash Uploader script was modified to export information from users' CI environments to a third-party server; Codecov's own security update advised affected users to re-roll credentials located in CI environment variables (Codecov security update). In January 2023, CircleCI reported that an attacker used malware on an engineer's laptop to steal a session, reach production systems, and take customer environment variables, tokens, and keys — and asked customers to rotate everything stored on the platform (CircleCI incident report).
Read those two accounts and a pattern emerges: in both cases, the victims' repositories could have been immaculate. The secrets moved through infrastructure — build tooling and CI configuration — that no repo scanner inspects. That is the argument for the layered detection standard in Chapter 7, including checks that run from outside the pipeline.
Where AI assistance changed the math
Surface 8 deserves its own attention because it behaves differently from the other seven. A developer pasting a key into a chat window is using a collaboration surface (7). What is new is the loop:
- A developer gives the assistant context — files, errors, environment details — and context sometimes contains keys.
- The assistant optimizes for making things work. The fastest proof that an integration works is calling it with a real credential.
- Generated code imitates patterns already in the repository, including bad ones. One hardcoded key teaches the convention.
- Agent sessions produce diffs, and diffs get merged under time pressure with less scrutiny than hand-written changes.
- When a fix is reverted, a later prompt can reintroduce the same key — the leak returns.
Chapter 8 treats this workflow in full: least-privilege setups for assistants, review patterns for generated diffs, and how monitoring catches reintroduction. The framing matters here: none of this is carelessness unique to AI users. It is a structural consequence of giving a fast, confident helper access to both your secrets and your shipping path. Tools change; the surfaces stay.
Honest boundaries of the map
A few limits keep this book trustworthy:
- Runtime-assembled keys are invisible to static scanning. If JavaScript concatenates fragments into a key at runtime, neither a bundle scanner nor most repo scanners will recognize the result. The fix is architectural: do not assemble keys in the browser at all.
- Code behind a login is not reachable by URL-based scanning. Paste-the-bundle modes cover it manually.
- Mobile binaries are a real escape surface but outside the scope of browser-bundle scanning; treat Chapter 1's row 6 as a reminder that your key inventory extends beyond the web.
Do this now
- [ ] List the eight surfaces in a note next to your key inventory; every future incident response starts by asking which surfaces are involved.
- [ ] Pick one production app and check whether source maps are publicly fetchable (append
.mapto a bundle URL). - [ ] Read the CircleCI incident report once, end to end; it is the best free education available on why "rotate everything in CI" is a complete sentence.
- [ ] Ask whether any teammate has ever pasted a
.envfile into a chat, ticket, or AI prompt. The honest answer sets your starting stage in Chapter 9.