ghtier

Permission Model

GitHub does not have one permission system. Classic tokens use OAuth scopes, fine-grained tokens and Apps use resource permissions, people get roles, and keys have no scopes at all. This page lines them up: every way access can be granted, how one request turns into effective access, and the same capability written in each vocabulary. The Access Tiers pages tier each of them.

Five vocabularies

The short answer to "do roles, fine-grained tokens and Apps follow the same pattern?" is no. Fine-grained PATs, GitHub Apps and GITHUB_TOKEN share one family of permission names. Classic PATs and OAuth Apps use another. Roles, including custom roles, use a third list whose names do not match either. They only meet when GitHub checks a request.

OAuth scope

Classic OAuth scopes

Classic PATs, OAuth Apps

A short list of coarse scopes such as repo, workflow and admin:org. The token reaches every organization the user belongs to, limited only by what the user can do there.

Resource permission

Resource permissions

Fine-grained PATs, GitHub Apps, GITHUB_TOKEN

One permission per resource (Contents, Issues, Administration, Secrets, Workflows) set to none, read or write. Tied to one resource owner and a selection of repositories. GITHUB_TOKEN uses a subset of the same names.

Role

Roles and role permissions

Enterprise, organization, team and repository roles, including custom roles

A ladder of roles (Read, Triage, Write, Maintain, Admin; Member, Owner) plus action-level extras such as Manage webhooks or Delete issues. The names do not match the resource permission list.

Key

Keys and certificates

SSH keys, SSH certificates, deploy keys, App private keys, webhook secrets

No scopes at all. Access is whatever the key is attached to: a user's full Git access, one repository, or every installation of an App.

Setting

Settings and policies

Enterprise and organization policies, environment rules, account settings

Not a grant on their own. They decide which grants are allowed, and they gate every token and role at request time.

How a request becomes access

Every request passes through the same five steps. The principal holds grants, presents one credential, and policy decides whether the request goes through. The credential can only narrow what the grants allow.

Principal

Who or what acts

  • Human (EMU or personal account)
  • GitHub App
  • Workflow run
  • Machine with a deploy key
  • AI agent

Grant

What it has been given

  • Enterprise role or custom role
  • Org role, pre-defined or custom
  • Org base permission
  • Team membership
  • Repo role or custom repo role
  • Bypass actor, env reviewer, code owner
  • App installation

Credential

The ceiling of one request

  • Classic PAT, OAuth token (scopes)
  • Fine-grained PAT (resource permissions)
  • App installation or user token
  • GITHUB_TOKEN (one repo, one job)
  • Web session
  • SSH key, SSH certificate, deploy key

Gates

Policy at request time

  • SAML SSO authorization
  • IP allow list
  • PAT and OAuth app policies
  • Rulesets and branch protection
  • Enterprise policies

Resource

What is reached

  • Repositories and code
  • Secrets and variables
  • Runners
  • Packages and releases
  • Org and enterprise settings

One path skips the gates

A workflow with id-token: write gets an OIDC token and trades it for cloud credentials. From there the cloud provider's trust policy is the only check. See GITHUB_TOKEN: id-token: write.

Effective access = what the principal is (role grants) ∩ what the credential allows (token ceiling) ∩ what policy lets through (gates).

  • A token never adds access the user does not have. A fine-grained PAT with Contents: write on a repo where the user only has Read can still only read.
  • App installation tokens and GITHUB_TOKEN have no user behind them, so the role part drops out and the App or workflow permissions are the whole grant.
  • An OIDC token from id-token: write leaves GitHub. The cloud trust policy is then the only gate, and none of the GitHub grants above apply.
  • Rulesets apply to everyone except the bypass list, so a bypass entry outranks any role.

Every way to grant access

25 mechanisms, from enterprise roles down to a single deploy key. The Workload rows are grants that only exist while a workflow or agent runs. Use this as the inventory list for an access review: each row is a place someone can hold access that another row will not show you.

MechanismPlaneGranted byReachesLifetimeVocabularyOn Access Tiers
Enterprise role: Owner, Billing manager, App manager, Security manager, UserEnterpriseEnterprise owner, or the IdP for EMUEvery organizationUntil removedRole
Guest collaborator (EMU only)EnterpriseIdP provisioning, then an org or repo admin grants accessOnly the repositories and orgs they are added toUntil deprovisionedRole
Enterprise custom role and enterprise teamsEnterpriseEnterprise ownerThe enterprise settings the role coversUntil removedRole
Organization role: Owner, Member, Moderator, Billing managerOrganizationOrganization ownerOne organizationUntil removedRole
Pre-defined organization role: Security manager, App manager, CI/CD admin, All-repository read to adminOrganizationOrganization ownerOne organization, every repository for the all-repository rolesUntil removedRole
Custom organization role: org permissions plus an optional base repository roleOrganizationOrganization owner, or defined once for the enterpriseOne organizationUntil removedRole
Organization base permission: none, read, write or adminOrganizationOrganization ownerEvery repository, for every memberUntil changedRole
Team membership: member or maintainer, inherited through child teamsOrganizationOrganization owner, team maintainer, or IdP group syncThe repositories the team was givenUntil removedRole
Direct repository role: Read, Triage, Write, Maintain, AdminOrganizationRepository adminOne repositoryUntil removedRole
Custom repository role: an inherited role plus additional permissionsOrganizationOrganization owner defines it, repository admin assigns itOne repository per assignmentUntil removedRole
Outside collaboratorOrganizationRepository admin, if org policy allows itThe named repositories only, with any repository role up to AdminUntil removed by hand. SSO is not required for outside collaborators, so IdP offboarding and SCIM do not remove themRole
Trigger-borrowed access: a fork pull request or issue comment that starts a workflowWorkloadWhoever wrote the workflow and chose its trigger (pull_request_target, issue_comment, workflow_run)What that workflow's GITHUB_TOKEN, secrets and runner can reach, used by someone who holds no role at allOne workflow runResource permission
Special grants: ruleset bypass actor, environment required reviewer, code ownerOrganizationRepository admin or org owner; anyone who can edit CODEOWNERSThe rules, environments or paths they coverUntil removedRole
Classic personal access tokenUserThe userEvery organization the user belongs toExpiry optionalOAuth scope
Fine-grained personal access tokenUserThe user, plus org approval when requiredOne resource owner, selected repositoriesExpiry requiredResource permission
OAuth App authorizationApplicationUser consent, plus org approval when OAuth access is restrictedEvery organization the user lets it reachUsually no expiryOAuth scope
GitHub App installationApplicationOrg owner, App manager, or repo admin for selected reposAll repositories or a selection1-hour tokens; the private key never expiresResource permission
GitHub App user access tokenApplicationA user signing in to the AppThe App's permissions and the user's own access, whichever is smaller8 hours, refreshable for 6 monthsResource permission
GITHUB_TOKENWorkloadThe workflow's permissions block, or the org or repo defaultOne repository, one jobThe job's durationResource permission
OIDC token from id-token: writeWorkloadThe workflow file, and the cloud trust policy that accepts itWhatever the cloud role allowsMinutesResource permission
Self-hosted runner and runner group accessWorkloadRepo admin, org owner or CI/CD adminThe repositories and workflows allowed to use the runnerUntil removedSetting
Copilot cloud agent, MCP servers and AI steps in workflowsWorkloadA user assigning the task, within org and enterprise policyWhatever token and tools it is givenOne task or one jobResource permission
SSH key on a user accountUserThe userAll the user's Git accessNo expiryKey
SSH certificate authorityOrganizationOrganization or enterprise ownerGit access as any member the certificate namesCertificate validityKey
Deploy keyOrganizationRepository adminOne repository, read-only or read-writeNo expiryKey

Crosswalk: one capability, every vocabulary

The same action written as a classic scope, a fine-grained or App permission, a GITHUB_TOKEN permission and a role. A dash means that vocabulary cannot grant it. When you review a token or role, find the capability here to compare it with the others; every tier on the right is on the same scale.

CapabilityClassic PAT / OAuthFine-grained PAT / AppGITHUB_TOKENRoleOn Access Tiers
Read coderepo (public_repo for public repos)Contents: readcontents: readRead
Push coderepoContents: writecontents: writeWrite
Change files under .github/workflows

GITHUB_TOKEN has no workflows permission, so a workflow cannot rewrite workflow files with its own token.

workflowWorkflows: write–Write
Start or re-run workflowsrepoActions: writeactions: writeWrite
Open, approve and merge pull requests

GITHUB_TOKEN can only approve when the org or repo allows Actions to create and approve pull requests.

repoPull requests: writepull-requests: writeWrite
Change repository settings and branch protectionrepo, as an adminAdministration: write–Admin
Delete a repository or change its visibilitydelete_repo (delete); repo, as an admin (visibility)Administration: write–Admin, if org policy lets admins do it
Manage Actions secretsrepo (repository); admin:org (organization)Secrets: write–Admin, CI/CD admin, or a custom role with secrets permissions
Register self-hosted runnersrepo (repository); admin:org (organization); manage_runners:enterpriseAdministration: write (repository); Self-hosted runners: write (organization)–Repository admin, org owner, CI/CD admin
Publish packages

One of the few places where a fine-grained PAT is not an option, so teams fall back to long-lived classic tokens.

write:packages– (GitHub Packages only accepts classic PATs)packages: writeWrite
Get cloud credentials through OIDC––id-token: writeAnyone who can change a workflow on a branch the cloud trust policy accepts
Manage organization members and teamsadmin:orgMembers: write (organization)–Org owner; team maintainer for their own team
Manage organization webhooksadmin:org_hookWebhooks: write (organization)–Org owner, or a custom organization role
Install or change GitHub Apps

Installing an App is done in the browser, not with a token scope, so only roles control it.

–––Org owner, App manager; repo admins for Apps that ask for no org or Administration permission, unless the org turns that off
Push past branch rules– (follows the user)– (follows the user or App)–Ruleset bypass actor
Enterprise administrationadmin:enterpriseLimited; check GitHub's list before relying on it–Enterprise owner

Credential model per type

Every kind of grant has a fixed credential model: who holds it, how far it reaches, how long it lives and who hands it out.

TypeVocabularyPrincipalReachesLifetimeGranted by
classic-pat-scopeOAuth scopeHumanEvery organization the user belongs to; SAML SSO orgs also need the token authorizedExpiry optional; an enterprise or org can set a maximumThe user, for themselves
oauth-app-scopeOAuth scopeHuman, through an appEvery organization the user grants it, unless the org restricts OAuth app accessUsually no expiry; lives until revokedThe user, on a consent screen
actions-token-permissionResource permissionWorkflow runThe one repository the workflow runs inThe job's durationThe workflow file's permissions block, falling back to the org or repo default
ai-agentResource permissionAgent working for a userThe repository it was assigned to, plus any tools and MCP servers it is configured withOne task sessionA user assigning it work; org and enterprise policy decide whether it may run
app-tokenResource permissionApp, or App acting for a userThe App's permissions, cut down to the installation's repositories (and the user's own access for user tokens)1 hour for installation tokens; 8 hours for user tokens, with a 6-month refresh tokenMinted by the App with its private key, or by a user signing in to the App
fine-grained-pat-permissionResource permissionHumanOne resource owner (a user or an org) and the repositories picked for the tokenExpiry required; 366 days by default, an enterprise or org can lower itThe user, plus org approval when the org requires it
github-app-permissionResource permissionAppThe repositories each installation was given (all, or a selection)Installation tokens last 1 hour; the private key that mints them does not expireWhoever installs the App: an org owner, an App manager, or a repo admin for selected repos
codeownersRoleHuman or teamThe file paths listed for them, on branches that require code owner reviewAs long as the CODEOWNERS file names themAnyone who can change the CODEOWNERS file on the protected branch
custom-org-roleRoleHuman or teamOne organization; a base repository role applies to every repositoryUntil removedAn organization owner; the role can also be defined once for the whole enterprise
custom-repo-roleRoleHuman or teamOne repository per assignmentUntil removedAn organization owner defines it; a repository admin assigns it
enterprise-roleRoleHumanThe whole enterprise, or the part a custom role coversUntil removed, or until the IdP deprovisions the user (EMU)An enterprise owner, or the IdP for EMU
org-roleRoleHumanOne organization, often every repository in itUntil removedAn organization owner
repo-roleRoleHuman or teamOne repositoryUntil removedA repository admin or an organization owner
ruleset-bypassRoleRole, team or AppThe branches, tags or pushes the ruleset targetsUntil removed from the bypass listA repository admin, or an organization owner for org rulesets
team-roleRoleHumanEvery repository the team, and its child teams, have been givenUntil removed; can be synced from an IdP groupAn organization owner or a team maintainer
app-credentialKeyAppEvery installation of the App, or every delivery of a webhookNo expiry until rotatedThe App owner or an App manager
deploy-keyKeyMachineOne repository, read-only or read-writeNo expiryA repository admin
gpg-keyKeyHumanProves authorship of commits; grants no accessKey's own expiry, if setThe user
ssh-certificate-authorityKeyWhoever holds the CA private keyGit access as any member of the organization or enterprise that trusts the CAEach certificate's validity; the CA key itself does not expireAn organization or enterprise owner uploads the CA
ssh-keyKeyHumanAll Git access the user has, in every organizationNo expiryThe user
account-settingSettingHumanThe user's own accountUntil changedThe user, within what the org or enterprise enforces
enterprise-policySettingEnterpriseEvery organization in the enterpriseUntil changedAn enterprise owner
environment-settingSettingRepositoryDeployments to one environmentUntil changedA repository admin
runnerSettingMachineThe repositories and workflows allowed to use the runner or runner groupUntil removed; non-ephemeral runners keep state between jobsA repository admin, an org owner or a CI/CD admin