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 .env to .env.bak, or a build tool copies it into a public artifact, or the .gitignore entry gets lost in a refactor. git log now contains a production database password forever.
  • The shared zip. "Here's the project" — with .env inside, 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:

  1. Storage — the one secure home for secrets, with access control and audit trail
  2. Delivery — how secrets reach the places that need them (local dev, CI, servers)
  3. Consumption — the runtime reading them, usually still from the environment

What "storage done right" looks like

  • Structured by project and environment: acme/production vs acme/staging are 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

  1. Pick your most active project
  2. Move its secrets to central storage, organized by environment
  3. Delete every .env copy that is not strictly needed for local development
  4. Rotate the keys that ever lived in chat, docs or the repo — assume they are burned
  5. Point local dev at the central store, keep .env purely 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