Your .env file is the master key to your app. Three things can make it public — and you've probably done at least one.
Check 1: Is It in Your Git History?
The most common leak. You committed .env early in development, then added it to .gitignore later. The file is gone from your working directory, but it's still in every clone of your repo.
# Run this in your project root
git log --all --full-history -- .env
# If you see ANY output, your .env was committed.
# Someone can extract it with:
git show <commit-hash>:.env
# and see every secret that was in the file at that point.
This applies to .env.local, .env.production, and any other dotenv variant too. Check them all.
Check 2: Is It Accessible via URL?
Some deployment setups serve your project root as static files. That means https://yourapp.com/.env might return your secrets. This is more common than you think, especially with misconfigured Nginx, Apache, or static hosting.
# Check if your .env is web-accessible
curl -s -o /dev/null -w "%{http_code}" https://yourapp.com/.env
# 200 = your secrets are public. Fix it NOW.
# 403 or 404 = good, not accessible.
# Also check these common variants:
curl -s -o /dev/null -w "%{http_code}" https://yourapp.com/.env.local
curl -s -o /dev/null -w "%{http_code}" https://yourapp.com/.env.production
curl -s -o /dev/null -w "%{http_code}" https://yourapp.com/.env.backup
Checked .env manually? Your JS bundle might still have secrets. vibeAudit scans 40+ secret formats automatically. Also read: How Cursor leaks your keys.
Check 3: Is Your Private Repo Actually Private?
You might think "my repo is private, so my .env in git history is fine." It's not. Private repos leak through:
- Stolen GitHub tokens -- if any collaborator's token leaks, your repo is exposed
- Accidental public switch -- one click in repo settings makes everything public
- Forking -- if a collaborator forks to their account and it goes public
- CI/CD logs -- build logs sometimes print environment variables
Treat your git history as semi-public. Never store secrets in it.
How to Remove .env From Git History
If your .env was committed, you need to rewrite history to remove it. Deleting the file and committing again isn't enough -- the old version is still there.
# Option 1: git filter-branch (built-in, slower)
git filter-branch --force --index-filter "git rm --cached --ignore-unmatch .env" --prune-empty --tag-name-filter cat -- --all
# Option 2: BFG Repo Cleaner (faster, easier)
# Download from https://rtyley.github.io/bfg-repo-cleaner/
bfg --delete-files .env
git reflog expire --expire=now --all
git gc --prune=now --aggressive
# After either option, force push to overwrite remote history
git push origin --force --all
Rotate Everything
This is the step people skip. Removing the file from history isn't enough. If a secret was ever committed, assume it was stolen. Rotate every key that was in that file:
- Database passwords -- change them in your database and update your hosting env vars
- API keys -- regenerate in each provider's dashboard (Stripe, OpenAI, AWS, etc.)
- JWT secrets -- generate a new one, which will invalidate all existing sessions
- OAuth secrets -- regenerate in your OAuth provider's settings
Yes, this is painful. It's less painful than someone draining your Stripe account.
Prevent It Going Forward
# Add to .gitignore BEFORE your first commit
.env
.env.*
!.env.example
# Create a safe template for collaborators
cp .env .env.example
# Edit .env.example to remove actual values, keep variable names
# DB_PASSWORD=your_password_here
# STRIPE_SECRET_KEY=sk_live_replace_me
FAQ
Q: Is my .env file in my Git history?
Run git log --all --full-history -- .env to check. If any commits appear, your secrets are in your repo history even if you deleted the file.
Q: How long before a leaked secret gets discovered?
According to GitGuardian, secrets pushed to GitHub are discovered by bots within 4 hours on average.
You just spent 4 minutes reading this. Spend 30 seconds scanning. Paste your URL into vibeAudit — free, no signup. Read-only scan, your app is never modified.