Skip to content
apikey.tools
JWTTokens

Personal Access Token Scope & Permission Builder

Select scopes and see exactly what each one grants before you create the token.

JWTRuns in this tabInput not transmitted

Input

days

0 means never — which is almost always the wrong answer.

Output

computing

Scope selection usually happens in a hurry, in a provider UI, with checkboxes whose names do not say what they do. The result is a token with far more power than the job needs — which is fine until it leaks.

Read the grant, not the name

repo on GitHub sounds like read access to repositories. It is full control of every private repository the user can reach: read, write, delete, plus settings and webhooks. It is the most over-granted scope on the platform, chosen because it is the first one in the list that makes a CI job work.

The breakdown panel here states the grant for each scope in plain terms, and marks its privilege level:

  • READ — disclosure only. A leak exposes data.
  • WRITE — modification. A leak means destruction or injection.
  • ADMIN — privilege escalation. A leak means the attacker can grant themselves more access and persist.

One administrative scope changes the character of the incident entirely, which is why selecting any triggers a warning.

Find the minimum by subtraction

The reliable method: grant nothing, run the job, add the one scope the error message demands, repeat. It takes three iterations and produces a genuinely minimal token. Starting from a generous set and trimming later never happens, because there is no error to prompt it.

Split by privilege, not by convenience

One token doing deployment, monitoring and administration is one credential whose leak costs you everything. Three tokens, each scoped to its job, mean a leak costs you one third and can be revoked without breaking the others.

The pattern that works:

  • A long-lived, read-only token for monitoring.
  • A write-scoped token for CI, restricted to the repositories it builds.
  • An administrative token that is short-lived and issued on demand, never stored in CI.

Always set an expiry

A non-expiring token stays valid in every backup, log, screenshot and abandoned laptop it ever reached. Ninety days is a reasonable default. GitHub's fine-grained tokens require an expiry precisely because unbounded classic tokens caused so many incidents.

Frequently asked questions

What is the difference between GitHub classic and fine-grained tokens?

Classic tokens use coarse scopes that apply to everything the user can access. Fine-grained tokens select specific repositories and specific permissions, and require an expiry. Use fine-grained for anything new; the granularity is the whole point.

Can I add a scope to an existing token?

No. Scopes are fixed at creation. You issue a new token with the scopes you need and revoke the old one — which is a good forcing function for thinking about the minimum.

How do I know which scope an API call needs?

The provider's endpoint documentation states it. Failing that, call the endpoint with no scopes and read the 403 — most providers name the missing scope in the error. The 401 and 403 simulator shows what those responses look like.

What if a scope I need is administrative?

Isolate it. Issue a separate short-lived token for that specific operation, ideally with human approval, and do not store it alongside your CI credentials. The blast radius analyzer quantifies what the separation saves you.

More tokens tools

Decode and dissect bearer credentials