Updated · 3 min read
the short answer
I committed my .env file to GitHub. What do I do?
First rotate every secret key that was in the file, at the provider, because bots scan GitHub for keys within minutes and deleting the file does not remove it from git history. Then stop tracking the file (git rm --cached .env), add .env to .gitignore, and commit. Cleaning the history is optional once the keys are rotated. Public values such as a Supabase URL or anon/publishable key do not need rotating.
How common this is
In our 2026 study of 1,029 public AI-built apps, 15% had a .env file committed to the repository, about one app in seven. It usually happens because the project was pushed before a .gitignore existed, or the AI tool created the file and git added everything.
Step 1: rotate the secret keys (do this first)
Make a new key at each provider, put it in your hosting or Supabase secrets, then delete the old one. Until the old key is deleted, it still works for whoever copied it.
- Supabase service role or secret key (sb_secret_...): create a new secret key and delete the old one in the API keys settings. Legacy JWT keys are rotated by changing the JWT secret, which signs everyone out.
- Stripe secret key: Developers, API keys, roll the key
- OpenAI, Anthropic and other AI keys: revoke the key and create a new one
- Database passwords, SMTP passwords, webhook secrets, OAuth client secrets: change them all
Which values are public anyway
Lovable and Bolt projects often commit a .env with only the Supabase URL, project ID and anon or publishable key. Those ship in your website to every visitor and are safe to expose, as long as your RLS policies are right. Anything with VITE_ or NEXT_PUBLIC_ in its name is public too, which is why secrets must never get that prefix.
Step 2: stop tracking the file
Keep a .env.example with the variable names and empty values, so the next person knows what to set.
echo ".env" >> .gitignore
echo ".env.*" >> .gitignore
echo "!.env.example" >> .gitignore
git rm --cached .env
git commit -m "Stop tracking .env"
git pushStep 3 (optional): remove it from history
After rotating, the old keys in history are useless, so this is mostly tidiness. If you want it gone, use git filter-repo, then force push. Forks and clones made before keep their copy.
pip install git-filter-repo
git filter-repo --path .env --invert-paths
git push --force --allStop it happening again
- Turn on secret scanning and push protection in the GitHub repository settings (free for public repositories)
- Add .env to .gitignore before the first commit of every project
- Check for usage you did not make on each provider's dashboard over the next days
Questions
Is deleting the .env file from GitHub enough?
No. The file stays in the git history, and bots that scan GitHub may already have copied the keys. Rotate the keys first.
My repository is private. Do I still need to rotate?
It is less urgent, but everyone with access and every tool connected to the repository can read the keys. Rotate anything powerful, and do it before ever making the repository public.
Do I need to rotate my Supabase anon key?
No. The anon and publishable keys are meant to be public. Only the service role or secret key must be rotated if it leaked.
How fast do leaked keys get used?
Often within minutes for AI and cloud keys, because automated scanners watch every public push. Treat a public leak as already used.