pwnmyvibecode_

Your GitHub token leaked

A GitHub token is never safe to expose: it acts as you, with whatever scopes or repository access it was given. Revoke it under Settings, Developer settings, Personal access tokens, check your security log and repos for changes, and replace it with a fine-grained token or a GitHub App that expires.

Updated

Check your live site now

Free, no signup, read only. A grade and plain fixes in seconds.

What GitHub tokens look like

  • ghp_: a classic personal access token. With the repo scope it reaches every repository you can, including private organisation ones.
  • github_pat_: a fine-grained personal access token, limited to repositories and permissions you picked.
  • gho_: an OAuth app access token.
  • ghu_: a GitHub App token acting for a user.
  • ghs_: a GitHub App installation token, used server to server.
  • ghr_: a refresh token for a GitHub App.

None of them are public. The prefix tells you what kind of token it is, which tells you where to revoke it.

How GitHub tokens end up on websites

  • A portfolio or dashboard calling the GitHub API from the browser with a token, to get past the unauthenticated rate limit.
  • A save-to-GitHub or CMS feature that commits content straight from the front end.
  • A token in a git remote URL (https://ghp_...@github.com/...) inside a .git folder that got deployed along with the site. Anyone who fetches /.git/config gets it.
  • Build scripts, CI files or .env files committed to a public repository.

GitHub automatically revokes tokens it finds pushed to a public repository or gist. A token sitting in your site's JavaScript or your server's .git/config isn't on GitHub, so don't expect it to be revoked for you.

What someone can do with a leaked GitHub token

It depends on the scopes or permissions, but a typical classic token can:

  • Clone your private repositories, including any secrets committed in them.
  • Push commits. If your site deploys automatically from main, that's a path to changing your live app.
  • Edit GitHub Actions workflows (with the workflow scope), which can be used to read your Actions secrets.
  • Delete repositories (with delete_repo) and act in organisations you belong to.

How to revoke a leaked GitHub token and check for damage

  1. If you're not sure whose token it is, ask the API (below). For classic tokens the response headers also list its scopes.
  2. Revoke it. For personal access tokens go to Settings, Developer settings, Personal access tokens, choose Fine-grained tokens or Tokens (classic), and delete it. For an OAuth app token, revoke the app under Settings, Applications.
  3. Read your account's security log in Settings, and your organisation's audit log if the token had org access. Look for new tokens, SSH keys, deploy keys, webhooks and collaborators.
  4. Check recent commits, branches and workflow file changes in the repos it could reach.
  5. Rotate any secret stored in those repos or in their Actions secrets if the token could read or change them.
  6. Remove the token from your code, your deployed files and your git history.
terminal
# Who owns this token, and (classic tokens) what scopes does it have?
curl -sI -H "Authorization: Bearer ghp_..." https://api.github.com/user | grep -i x-oauth-scopes
curl -s -H "Authorization: Bearer ghp_..." https://api.github.com/user | grep '"login"'
terminal
# 1. Put the leaked value in a file, one per line, mapped to a placeholder
echo 'PASTE_THE_LEAKED_KEY_HERE==>REMOVED' > replacements.txt

# 2. Rewrite every commit (work on a fresh clone, keep a backup)
git filter-repo --replace-text replacements.txt

# 3. Force push the rewritten branches, then delete replacements.txt
git push --force --all

How to use the GitHub API without exposing a token

  • For public data, call the API without a token (the unauthenticated limit is 60 requests an hour per IP), or fetch on your server with a token and cache the result.
  • Keep any token in a server-only env var and call GitHub from a server route.
  • For automation, use a GitHub App. Its installation tokens expire after an hour.
  • If you need a personal token, make it fine-grained: one repository, the fewest permissions, and an expiry date.
  • Turn on push protection so GitHub blocks commits that contain recognised secrets.

Our scan flags classic ghp_ tokens in your page HTML and your site's own JavaScript, and checks whether /.git/config is publicly downloadable. It does not currently detect fine-grained github_pat_ tokens or the other prefixes, so search your build output for those yourself.

Questions

Is a GitHub token with no scopes dangerous?

A classic token with no scopes can only read public information as you, so the risk is low. Revoke it anyway; there's no reason for it to be public.

Are fine-grained tokens safe to expose?

No. They limit the damage to the repositories and permissions you chose, but whatever they can do, anyone holding them can do.

Does push protection stop this?

It blocks pushes containing supported secrets to repositories where it's on, though a person can choose to bypass it. It doesn't cover tokens in your deployed site or on your server.

Does your scan detect GitHub tokens?

It detects classic ghp_ personal access tokens in public HTML and JavaScript. It doesn't detect github_pat_ fine-grained tokens today.