Keys committed to GitHub
A key in a commit is copied to every clone and to GitHub's history. Deleting the file in a new commit does not remove it.
Last updated
Shows up in: GitHub, Supabase, Vercel, Next.js
What it is
Git stores history. If .env, a service account JSON, or a hardcoded key was committed, it is still in older commits after you delete the file. If the repository is public, GitHub's secret scanning can see it. If the repository is private, everyone with access, every fork, and every CI log that printed the file still counts as a leak.
GitHub documents that secret scanning runs for public repositories, and that push protection for users blocks accidental secret pushes to public repositories by default. That is a backstop, not a substitute for keeping secrets out of the tree. Partner alerts mean GitHub may tell the service that issued the token. Assume a pushed key is burned and rotate it.
Making the repo private afterward does not un-copy a key that was already public.
How to check in 5 minutes
Run
git log -p -- .env .env.local .env.productionand search history forsb_secret_,service_role,sk_live_, andPRIVATE KEY. Deleting the file on the current branch is not the check.On GitHub, open the repository Security tab and look at secret scanning alerts if the repo is public. GitHub documents these alerts as available for public repositories by default.
Confirm
.env*is in.gitignore, and thatgit statusdoes not list an env file. A sample file such as.env.examplemay be committed if it contains only placeholder values.Search GitHub Actions logs and Vercel build logs for echoed secrets if a workflow printed the environment.
How to fix
GitHub
Rotate the key at the provider first. Then remove it from history if the repo was shared or public. History rewriting (git filter-repo or a similar tool) changes commit hashes and requires everyone to re-clone. Do not rewrite history until you understand that it disrupts open pull requests. Rotation matters more than a pretty history: a rewritten public repo can still have been scraped.
Turn on secret scanning and push protection where GitHub offers them for your repo. For a public repository, GitHub's security features page says secret scanning alerts and push protection are available by default. Private repositories need GitHub Secret Protection, which is a paid product on Team or Enterprise Cloud. Do not assume a private hobby repo is being scanned.
Add a .gitignore entry before the next commit:
.env
.env.*
!.env.example
Supabase
Create a new secret key, switch the server to it, then revoke the leaked key and the legacy service_role key if that was what got committed. Supabase's rotation note says to fix the cause before you rotate, and to confirm every component uses the new key before you retire the old one.
Vercel
Update the environment variable to the new value and redeploy. Remove the secret from any preview deployment that built the bad commit.
Next.js
Read secrets from the environment at runtime on the server. Do not default them in source code "for local dev." Use .env.local, which Next.js gitignores in a typical app, and keep .env.example free of real values.
Copy-paste prompt
Paste this into Cursor, Claude Code, or whichever agent is editing the repo. Read the diff before you merge it.
You are cleaning secrets out of this git repository. Do not add features. 1. Search tracked files for service_role, sb_secret_, sk_live_, sk_test_, webhook secrets, and private keys. Search git history for .env files if you can do that locally. 2. Make sure .gitignore ignores .env and .env.* while still allowing .env.example. 3. Replace real secrets in tracked files with a reference to an environment variable. Put placeholder names, not real values, in .env.example. 4. Do not rewrite git history unless I explicitly ask. Tell me which keys I must rotate because they were committed. 5. Do not print the secret values in your summary. List the files and the provider keys I need to rotate.
Questions
I deleted .env in the latest commit. Are we done?
No. The blob is still in older commits. Rotate the key. History cleanup is a second step, and it does not help if someone already cloned the repo.
Will GitHub scan my private repository for free?
GitHub's docs say secret scanning alerts and push protection are available for public repositories by default. Organization-owned private repositories need GitHub Secret Protection. A personal private repo should not be treated as covered unless you have confirmed it in the repo's security settings.