Fix guide · high · exposed_env_staging

.env.staging file deployed to production

What this rule means

A /.env.staging file is reachable at your production root. It contains environment variables your staging environment uses — often a subset of production creds, but frequently reusable against staging surface or revealing internal service names.

Why it matters

Staging environments tend to share more with production than operators realise:

Even when the credentials in .env.staging are throwaway, the file's variable NAMES reveal which third-party services you depend on (Datadog, Stripe, Twilio, SendGrid, Postmark, etc.), which feature flags exist, and which internal microservices the staging app talks to. That's a reconnaissance map.

How it ends up deployed: build tool copies .env.* patterns indiscriminately, or a build script does cp .env.staging dist/ instead of cp .env.production dist/, or someone debugging production-staging-parity issues left the file in the deploy.

How to fix it

  1. Delete the file from your production deploy immediately. Push a build that excludes it.
  2. Rotate any credential in the file that is shared with production. Don't assume "but it's only staging" — assume it's already been harvested.
  3. Audit your build script. Production builds should ONLY include the env vars the production runtime reads. cp .env* is too broad; be explicit: cp .env.production dist/.env.
  4. Add a guard: post-build check that fails the deploy if any .env.* file ends up in the public output directory.
  5. At the edge, block all .env* paths: _redirects returning 404, or a Pages Function returning 404 for any path matching /\.env.*.

Did vibecheck flag this on your app?

If you reached this page from a vibecheck inspection report, the redacted match in your scan output is the exact string we found in your bundle. After applying the fix above, run the inspection again — the finding should clear.

Run another inspection