Cursor wrote a GitHub Action with a token that has full repo scope. It is now in three places. Here is how to find and revoke it.
You asked Cursor to wire up a GitHub Action that builds a Docker image and pings Slack when staging deploys. It worked on the first try. Buried in the script is a GITHUB_TOKEN with `repo` and `workflow` scopes, which you copied from your settings page three weeks ago. It now lives in a `.env.production` that got pulled into a Vercel preview, in the bash history of your dev container, and in a Notion page where you pasted it once because the workflow was failing. The token still works. It still has push access to every private repo you own, including the one with the Stripe webhook secret and the Supabase service role key. The recent GHSA-5wxr-w449-57cm advisory and the CISA leak GitGuardian got pulled down in 26 hours both come back to the same thing: tokens with too much scope, sitting in too many places, that nobody is watching.
02The token Cursor wrote has too much scope
When you click Generate new token (classic) on github.com/settings/tokens, GitHub shows a wall of checkboxes. Cursor, Bolt, and Lovable do not know which ones your specific job needs, so they tell you to check `repo` and call it done. `repo` is not one permission. It is read and write to all your private and public code, your commit history, your deploy keys, your webhooks, and your repo settings. If that token leaks, an attacker can push a `package.json` change with a postinstall script and ship malware through your next CI run. They can also rewrite your README to point at a phishing page, and your users will trust it because it is your repo. The fix is fine-grained tokens. Go to github.com/settings/personal-access-tokens. Create a new one. Pick the exact repositories the workflow touches. Pick the exact permission (Contents: Read, Actions: Write) the job needs. Set expiration to 30 days, not no expiration. One check you can run right now: open every `.env`, every GitHub Action workflow, and every Vercel project's environment variables. For each `GITHUB_TOKEN`, `GH_TOKEN`, or `GH_PAT` you find, paste the prefix into github.com/settings/tokens and look at its scopes. If it says `repo` and the job only needs to read one file from one repo, replace it before lunch.
03Where your GitHub token actually leaks from
You think your token is safe because it is in an environment variable. It is not. Here is where it actually shows up. Your Vercel preview deployments. Every preview branch gets its own URL and its own build logs. If your build script does `echo $GITHUB_TOKEN` for debugging, that string sits in the build log of a public preview that any indexer can scrape. The CISA leak GitGuardian found was this pattern at federal scale. Your Cursor session logs. When you paste a token into chat to ask the model why is this not working, it goes into the prompt context and possibly into Cursor's logs. Your Notion pages, your Linear comments, your Slack DMs to yourself. Founders treat these like password managers. They are not. Your `git stash` and old branches. You may have removed the token from `main`, but `git log --all -p | grep -i ghp_` will find it in a stashed commit from two weeks ago. GitHub Push Protection only blocks new commits. It does not retroactively scrub history. Run this today in your repo: `git log --all --full-history -p | grep -E 'ghp_|github_pat_|gho_'`. If anything matches, that token must be revoked, not rotated. Then check github.com/settings/security-log for token events you do not recognize, and your Vercel build logs for the string `ghp_`. If you find a hit anywhere, assume the token is public.
04What to rotate, what to revoke, what to scan
Rotating means generating a new token and swapping it in. Revoking means killing the old one at github.com/settings/tokens so the leaked copy stops working. Founders rotate and forget to revoke. The old token, in the old screenshot, in the old Slack thread, still works. Every token leak needs both. Generate the new fine-grained token. Update the workflow, the Vercel env, the local `.env`. Then go to GitHub and click Delete on the old one. Then check github.com/settings/security-log for any actions the token took in the last 90 days. If anything looks wrong, a push you do not remember, a workflow run you did not start, assume worst case and rotate every other secret in that repo: Stripe keys, Supabase service role, OpenAI API key, anything in `.env`. If your repo has tokens in commit history, turn on Push Protection and Secret Scanning at github.com/your-repo/settings/security_analysis. Both run free on public repos. This is the first thing Guardian does on a scan. We walk every workflow file, every committed `.env`, and every preview environment, find the tokens, check whether they are still live against the GitHub API, and tell you which ones to revoke first. You do not have to remember where you pasted what.
Find every live GitHub token in your repo
Guardian scans your workflows, commit history, and Vercel envs for leaked GitHub PATs, checks which ones still work against the GitHub API, and tells you which scopes to revoke first.
Scan my app free