GitHub tokens explained: PAT classic, fine-grained, OAuth — and their blast radius
Same word, very different reach
When someone says 'a GitHub token,' that could mean several different things — and the difference matters most at the worst moment, when one leaks. Two tokens can look identical as a string in a log or a bundle, yet one unlocks a single repository while the other unlocks your entire account. The useful way to understand GitHub tokens is by blast radius: what an attacker gets if they get the token.
Classic personal access tokens (PATs)
The original PAT. You grant it coarse scopes like repo or admin:org, and crucially those scopes apply across everything your account can touch. A classic PAT with the repo scope can read and write every repository you have access to, not just one.
That makes the blast radius large. A leaked classic PAT is, roughly, a leaked copy of your account's access for whatever scopes it holds. They are convenient, which is exactly why they over-grant.
Fine-grained personal access tokens
The modern replacement, built specifically to shrink blast radius. A fine-grained PAT is restricted in two ways at once:
- Repository selection — you choose exactly which repositories it can touch, often a single one.
- Granular permissions — you grant specific capabilities (read contents, write issues) instead of a broad scope.
They also expire. A leaked fine-grained token limited to one repo with read-only contents is a far smaller incident than a classic PAT — the reach is bounded by design. This is the type to prefer.
OAuth tokens
These are issued when you authorize a third-party app to act on your behalf via 'Sign in with GitHub.' The token's reach is whatever permissions you approved during that consent flow. The blast radius therefore depends on the app and what it asked for — and on the app keeping the token safe, which is now partly out of your hands.
GitHub Apps (as opposed to OAuth apps) go further, issuing short-lived installation tokens scoped to specific repos and permissions, which is generally the tightest option for automation.
Why tokens leak — and it is ordinary
Tokens leak the same mundane ways every secret does: committed to a repo, baked into a CI config, pasted into a client-side build, left in a log. None of it requires a clever attack, and none of it is a scandal — it is normal hygiene that slipped. The reason it stings with GitHub tokens is that automated bots scan public code for token formats constantly, and your source is the one place a code-hosting token most often ends up.
Keeping the blast radius small
- Prefer fine-grained PATs or GitHub App tokens. Least privilege by default.
- Scope to the minimum. One repo, the fewest permissions, the shortest expiry that works.
- Keep them out of code. Use secrets storage and CI secret managers, never a committed file or a client bundle.
- Rotate on any exposure. If a token was ever public, revoke it and issue a new one. Assume it was found.
Check what your site exposes
A token committed to a repo is one problem; a token that made it into your shipped frontend or a reachable file is another. An automated scan reads your live site the way a bot would and flags exposed tokens and secrets. Scan your site and see what is reachable.