← All posts
next.jssecurity.envexposed secretsvibe coding

Exposed .env File Next.js Fix: A Developer's Complete Guide

O

OverMCP Team

Quick answer

If you’ve accidentally exposed your .env file in a Next.js app, immediately rotate all secrets (API keys, database passwords, tokens) and remove the .env file from version control history. For ongoing protection, add .env to .gitignore, use environment variables in Vercel/Netlify, and run a secret leak scanner to catch any lingering exposures.

What to check first

Before you panic, run through this checklist to assess the damage:

  • [ ] Is your `.env` file publicly accessible? Try visiting https://yourdomain.com/.env. If you see your secrets, they are exposed.
  • [ ] Is `.env` in your Git history? Run git log --diff-filter=A -- .env to see if the file was ever committed.
  • [ ] Are there secrets in your client-side bundle? Check browser DevTools → Sources → search for keys like sk-, AKIA, or SG..
  • [ ] Are you using environment variables correctly? In Next.js, variables prefixed with NEXT_PUBLIC_ are exposed to the browser. Non-public keys must only be used in server-side code (API routes, getServerSideProps, middleware).
  • [ ] Have you rotated exposed secrets? Assume any key that was ever in an exposed .env is compromised.
  • [ ] Are your deployment environment variables set? Check Vercel, Netlify, or your cloud provider to ensure secrets are stored there, not in the repo.
  • Step-by-step fix

    1. Remove `.env` from version control

    If you accidentally committed .env, remove it from Git history using git filter-branch or the simpler git rm:

    git rm --cached .env
    echo ".env" >> .gitignore
    git add .gitignore
    git commit -m "Remove .env from repo and add to .gitignore"

    To completely purge it from history (use with caution if you have collaborators):

    git filter-branch --force --index-filter \
      "git rm --cached --ignore-unmatch .env" \
      --prune-empty --tag-name-filter cat -- --all

    Then force push to rewrite history:

    git push origin --force --all

    2. Rotate all secrets

    Assume every secret in the exposed file is compromised. Generate new keys:

  • OpenAI API key: Revoke old key in the API keys dashboard.
  • Stripe secret key: Regenerate in the Stripe dashboard.
  • Supabase service role key: Go to your Supabase project → Settings → API → regenerate service_role key.
  • Database URL: Update the password in your database provider and update the connection string.
  • Update your deployment environment variables with the new values.

    3. Use Next.js environment variables correctly

    Create two files – one for local development and one for production secrets:

    # .env.local (local only, never committed)
    DATABASE_URL=postgresql://user:password@localhost:5432/mydb
    OPENAI_API_KEY=sk-...
    STRIPE_SECRET_KEY=sk_live_...
    
    # .env.example (committed, shows required vars without values)
    DATABASE_URL=
    OPENAI_API_KEY=
    STRIPE_SECRET_KEY=

    In next.config.js, ensure you’re not accidentally exposing server-only variables:

    // next.config.js
    module.exports = {
      env: {
        // Only put values that are safe for the client here
        NEXT_PUBLIC_ANALYTICS_ID: process.env.NEXT_PUBLIC_ANALYTICS_ID,
      },
    };

    Best practice: Use NEXT_PUBLIC_ prefix only for values that must be in the browser (e.g., public API keys for Firebase). All other secrets should be accessed only in server-side code via process.env.SECRET.

    4. Add a `.gitignore` entry

    Ensure .env is in your .gitignore from the start:

    # .gitignore
    .env
    .env.local
    .env.production
    .env.*.local

    5. Scan for remaining leaks

    Use a free AI app security scanner to check your entire Git history and current deployment for exposed secrets. This will catch:

  • Secrets in past commits
  • Secrets in client-side JavaScript bundles
  • Hardcoded keys in source files
  • 6. Set up continuous monitoring

    Enable continuous security monitoring on your repository so you’re alerted immediately if any new secrets are accidentally pushed.

    Common mistakes

  • Using `.env` instead of `.env.local`: Next.js loads .env, .env.local, .env.development, etc. but only .env.local is ignored by default in some setups. Always use .env.local for local development keys.
  • Committing `.env.example` with real values: Developers often copy .env to .env.example and forget to blank out the secrets. Use placeholder values like your-api-key-here.
  • Putting secrets in `NEXT_PUBLIC_` variables: Any variable prefixed with NEXT_PUBLIC_ is inlined into the client bundle. Never store API keys, database passwords, or other secrets there.
  • Forgetting about `.env.production`: If you use .env.production locally but deploy via Git, that file could be committed. Use .env.production.local for local overrides.
  • Not checking Git history: Even if you delete the file now, the secret may exist in an older commit. Attackers often scan public repos for past commits containing secrets.
  • How to prevent future exposures

  • Add `.env` to `.gitignore` immediately when scaffolding a project. Vibe-coded apps often skip this step.
  • Use a pre-commit hook to block committing files containing secrets. Tools like husky with lint-staged can run a secret scanner before each commit.
  • Store secrets in your deployment platform (Vercel, Netlify, Railway) and access them via environment variables there. Never duplicate them in a file.
  • Run a [security headers checker](https://www.overmcp.com/tools/headers) to ensure your site doesn’t leak sensitive files through misconfigured headers.
  • Use a [SSL certificate checker](https://www.overmcp.com/tools/ssl) to verify HTTPS is enforced, preventing man-in-the-middle attacks that could steal env vars in transit.
  • FAQ

    How do I check if my `.env` file is publicly accessible?

    Try visiting https://yourdomain.com/.env in a browser. If you see the file contents, it’s exposed. Also check /.env, /.env.local, and /.env.production. Use a secret leak scanner to detect leaks automatically.

    Can I recover a committed `.env` file without rewriting Git history?

    Yes, you can remove the file from the current commit and add it to .gitignore, but the file will still exist in previous commits. For a full removal, you must rewrite history using git filter-branch or BFG Repo-Cleaner, then force push.

    What should I do if my `.env` file was exposed but only for a short time?

    Immediately rotate all secrets in the file. Even a brief exposure can be scraped by automated bots. Change API keys, database passwords, and any tokens. Then scan your repo and deployment for any copies of the old keys.

    ---

    Protect your Next.js app from secret leaks. Scan your repo for free with [OverMCP](https://www.overmcp.com/).

    Is your app secure?

    Free scan in 30 seconds. No signup needed.

    Scan My App Free