Bush Coding Blog
Why Storing Secrets in .env Files Is a Problem (and What to Do Instead)
Every developer knows the ritual: clone a repo, copy .env.example to .env, paste in the real keys. It works beautifully — for a team of one, on one machine, on a project that never goes anywhere. The trouble starts the moment any of those three things changes.
How .env files actually leak
None of these are hypothetical; they are the standard ways secrets escape:
- The accidental commit. You rename
.envto.env.bak, or a build tool copies it into a public artifact, or the.gitignoreentry gets lost in a refactor.git lognow contains a production database password forever. - The shared zip. "Here's the project" — with
.envinside, because it was in the folder. The client forwards it to their new intern. - The screenshot. A screen share to debug, a capture of your editor, and your API keys are in someone's clipboard history.
- The departed laptop. The old machine still has a working copy of everything, and nobody rotated the keys when it left.
- The copy-paste sprawl. The same key ends up in three deployment tools, two CI variables pages and a Notion doc — and when it needs rotating, you find two of the five.
# Fine in local dev. A liability everywhere else:
DATABASE_URL=postgres://prod-user:hunter2@db.internal:5432/app
STRIPE_API_KEY=sk_live_51H8...
AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG
If any of that made you wince in recognition, keep reading.
The rule: .env is a format, not a storage strategy
There is nothing wrong with .env as a file format — twelve-factor apps still read configuration from the environment. What breaks is using the file as the source of truth: the single, authoritative, shared place where secrets live.
The mature setup separates three things:
- Storage — the one secure home for secrets, with access control and audit trail
- Delivery — how secrets reach the places that need them (local dev, CI, servers)
- Consumption — the runtime reading them, usually still from the environment
What "storage done right" looks like
- Structured by project and environment:
acme/productionvsacme/stagingare clearly separated, never guessed from filenames - Access per person: the intern does not need production keys; the frontend dev does not need the database URL
- Revocable instantly: someone leaves, you flip one switch — not a rotation ceremony across five services
- Auditable: who pulled the production credentials last Tuesday, and why, is answerable
- Works for machines too: a CLI or API so CI, scripts and deploys can pull secrets without a human copying files
Platforms built for this exist precisely because spreadsheets, chat and .env-in-repo kept burning teams. We built Stash for the same reason: a secure home for API keys and credentials — web dashboard for humans, CLI for the machines, running on Windows, macOS and Linux.
A practical migration, one project at a time
- Pick your most active project
- Move its secrets to central storage, organized by environment
- Delete every
.envcopy that is not strictly needed for local development - Rotate the keys that ever lived in chat, docs or the repo — assume they are burned
- Point local dev at the central store, keep
.envpurely as a runtime artifact that is never committed or shared
Repeat per project. It is an afternoon the first time and half an hour every time after.
FAQ
Isn't this what CI/CD secret variables are for?
CI variables solve delivery for CI — one of the three pieces. They do not give your laptop, your teammate, or your deploy scripts a shared, auditable source of truth. Most teams that rely on CI vars alone still have the "it's in a Notion doc somewhere" problem.
What about cloud provider secret managers (AWS Secrets Manager, etc.)?
They are solid — and deeply tied to their ecosystem, priced per secret, and awkward when your stack spans providers. Independent platforms make sense when you want one home for secrets that serve AWS, Vercel, Stripe and your homelab alike.
Is an .env file in local development actually dangerous?
By itself, on a single secure machine, it is acceptable risk — provided it is generated, not shared. The danger is the habit: the moment "send me your .env" enters your team's vocabulary, the file has become your password manager, and it was never built to be one.
Give your secrets a real home
Try Stash free