The .env file is publicly accessible

What it is

The .env file in the root of your site (https://example.com/.env) is freely accessible. When someone downloads it, they get everything stored inside.

Why it’s a problem

.env routinely contains:

Once an attacker gets these values, it’s usually game over. They download your database, sign a JWT with admin privileges, and send phishing through your SMTP. They don’t need to exploit anything in the application at all.

This is the most common “silly fail” we come across. It usually happens when an app is deployed via git pull straight into public_html and nobody realized that .env ends up in the webroot too.

How to fix it

Step 1 — block access immediately

nginx:

location ~ /\.env {
    deny all;
    return 404;
}

Apache (.htaccess in root):

<Files ".env">
    Require all denied
</Files>

After deploying, verify: curl -I https://example.com/.env — it should return 403 or 404.

Step 2 — ROTATE every secret that was in there

If .env was publicly accessible even for a moment, assume someone already has it. Generate new:

  1. Database password.
  2. All API keys (Stripe, Mailgun, etc. — look for “rotate” / “revoke” in their admin panels).
  3. JWT secret (after rotating it, all logged-in users will have to sign in again — that’s fine).
  4. SMTP password.

Step 3 — move .env outside the webroot

In the long run, .env belongs above the public_html level. The application reads it from an absolute path, and the web server can never reach it.

/var/www/example.com/
├── app/
│   └── .env          ← here
└── public_html/      ← document root
    └── index.php

Step 4 — check your git history

If .env was ever committed to git, it’s in the history forever. Use BFG Repo-Cleaner or git filter-repo and force-push. An open repo without a force-push = secrets still accessible.

References