---
title: "Exposed .env files and debug endpoints"
slug: exposed-env-and-debug-endpoints
severity: critical
category: Secrets
summary: "A public .env, a /api/debug route, or a client bundle that prints config hands your secrets to anyone who asks."
platforms:
  - Next.js
  - Vercel
  - Supabase
updated: "2026-10-13"
related:
  - secrets-committed-to-git
  - secret-keys-in-the-frontend
---

Three different mistakes get lumped together because the result is the same.

A file named `.env` is fetched from the website because it was copied into `public/` or deployed as a static file. The browser can request `/ .env` or `/env`.

A debug route an agent added, such as `/api/debug` or `/api/health?verbose=1`, returns `process.env` so the author could see why a key was undefined. That route is a directory of secrets.

A log line prints the config object on startup, and the host's log viewer is shared more widely than production.

Next.js exposes variables whose names start with `NEXT_PUBLIC_` to the browser. That is documented framework behavior, not a leak by itself. Putting a secret behind that prefix is the leak. See [secret keys in the frontend](/issues/secret-keys-in-the-frontend).

Source maps make your client code easier to read. They do not, by themselves, reveal server environment variables. They do reveal a secret you inlined into client code.

## How to check in 5 minutes

1. Request `/.env`, `/.env.local`, `/.env.production`, and `/env` on your deployed site. You want a 404, not a file.
2. Search routes for `process.env`, `JSON.stringify(process.env)`, and path names `debug`, `test`, and `health`. A health check may return `{ ok: true }`. It should not return config.
3. Confirm `public/` does not contain `.env` or a service-account JSON file. Everything in `public/` is a URL.
4. Search client components for `console.log` of session objects, keys, or full user records. Browser logs are visible to anyone using that browser, and to extensions.

## How to fix

### Next.js

Delete debug routes or guard them so they cannot run in production. Prefer deleting them. A health check returns status only.

Do not put `.env` in `public/`. Keep real env files gitignored. See [keys committed to git](/issues/secrets-committed-to-git).

If a secret was reachable, rotate it. Removing the route does not un-copy the value.

### Vercel

Set environment variables in the project settings, scoped to the environments that need them. Do not commit them for "convenience." If the host offers a way to mark a variable sensitive so the dashboard stops showing the value, use it. Confirm the current control in Vercel's environment variable docs rather than assuming a button label.

Turn off verbose logging of request bodies on auth and webhook routes.

### Supabase

The project URL and publishable key are not secret. The secret key, database password, and service role JWT are. The database password in a committed `.env` is a direct Postgres login. Rotate it in the dashboard if it leaked, not only the API key.

### Firebase

A downloaded service account JSON in the repo or in `public/` is a server credential. Rotate it in Google Cloud credentials if it was exposed. The Firebase web config object is different and is expected in client apps.

## Agent prompt

```text
You are removing debug exposure. Do not add features.

1. Find routes and pages that print process.env, config objects, or secrets. Delete them or make them return only { ok: true } with no secrets.
2. Make sure public/ and static export folders do not contain .env files or service account JSON.
3. Remove console.log calls that print tokens, keys, passwords, or full session objects.
4. Do not rename a NEXT_PUBLIC_ secret and leave the old value in git. Tell me which values I must rotate.

Do not print any secret in your summary. List files you deleted or changed.
```

## FAQ

### Our /api/health returns the git SHA. Is that a secret?

A SHA is not a password. It does tell an attacker which commit you run, which matters if that commit has a known bug. Returning `{ ok: true }` is enough for an uptime check.

### The .env file 404s. Are we done?

Check git history and old deployments too. A file that 404s today may have been public yesterday. If it ever contained a live key, rotate the key.

## Sources

- [Supabase API keys](https://supabase.com/docs/guides/api/api-keys)
- [GitHub secret scanning](https://docs.github.com/en/code-security/concepts/secret-security/secret-scanning)
