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:
- The database password (
DB_PASSWORD) - API keys — Stripe, Mailgun, AWS, OpenAI
- The JWT secret used to sign authentication tokens
- SMTP credentials for sending email
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 viagit pullstraight intopublic_htmland nobody realized that.envends 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:
- Database password.
- All API keys (Stripe, Mailgun, etc. — look for “rotate” / “revoke” in their admin panels).
- JWT secret (after rotating it, all logged-in users will have to sign in again — that’s fine).
- 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.phpStep 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.