GitHub Actions
GITHUB_TOKEN Permissions: Safer GitHub Actions CI/CD
Make `GITHUB_TOKEN` permissions explicit at the workflow top level, then grant write scopes only to the jobs that need them. The goal is not a clever YAML trick. The goal is that reviewers can see privilege before they merge a workflow change.
Key takeaways for `GITHUB_TOKEN` permissions
- GitHub says an action can access `GITHUB_TOKEN` through the `github.token` context even when the workflow does not explicitly pass the token to the action. [1]
- GitHub recommends limiting `GITHUB_TOKEN` to the minimum access required by the workflow or job. [1]
- GitHub documents `permissions` as the workflow key for setting `GITHUB_TOKEN` access, including `read-all`, `write-all`, `{}`, and per-scope `read`, `write`, or `none`. [2]
- GitHub documents that once any permission is specified, unspecified permissions are set to `none`. [2]
- OpenSSF Scorecard's Token-Permissions check rewards workflows that declare read-only permissions at the top level and put required write permissions at the job level. [4]
Make least privilege visible in the YAML
GitHub's authentication guide says workflows can use `GITHUB_TOKEN` for actions, GitHub CLI calls, and API requests. It also says actions can access the token through the `github.token` context even if the workflow does not explicitly pass it. [1] That is why token permissions deserve review even in workflows that do not show `secrets.GITHUB_TOKEN` in a step.
The practical control is the `permissions` key. GitHub says this key can be used for an entire workflow or for individual jobs, and that it lets maintainers configure the minimum required permissions. [1]
Default token access is too implicit for review
GitHub's workflow syntax reference lists `permissions` under the top-level workflow syntax and under `jobs.<job_id>.permissions`. [2] It also documents broad shortcuts, including `read-all`, `write-all`, and `{}`. [2]
Those shortcuts are useful when they make intent obvious. `permissions: read-all` tells reviewers the workflow starts read-only. `permissions: {}` tells reviewers the workflow starts with no token permissions. `permissions: write-all` usually deserves extra scrutiny because it hides which write capability the job truly needs.
A top-level baseline keeps accidental write scope out
GitHub documents that if a workflow specifies access for any permission, all permissions not specified are set to `none`. [2] That behavior lets teams use a short baseline instead of repeating every permission name.
- Read-only baseline: use `permissions: read-all` when most jobs only need to read repository contents and metadata.
- Narrow baseline: use `permissions: contents: read` when the workflow only needs repository content reads.
- No-token baseline: use `permissions: {}` when jobs should not receive repository token access unless a job explicitly opts in.
OpenSSF Scorecard mirrors that posture in its Token-Permissions remediation guidance: set top-level permissions as `read-all` or `contents: read`, then set required write permissions at the job level. [4]
Write scopes belong beside the step that needs them
GitHub's token guide uses job-level `permissions` examples for creating an issue with the GitHub CLI and with the REST API. [1] That pattern is useful because the permission sits near the behavior it enables.
A release job that publishes a package may need a package write scope. An issue triage job may need issue write scope. A cloud deployment using OpenID Connect may need `id-token: write`; GitHub's secure-use reference recommends considering OIDC for deployments that need short-lived, well-scoped cloud tokens. [3]
Pull-request workflows need token review before merge
Token scope interacts with workflow triggers. GitHub's workflow syntax reference notes special permission behavior for `pull_request_target`, and the CI Tripwire guide on `pull_request_target` security explains why privileged pull-request automation should stay away from untrusted pull-request code. [2]
For ordinary pull-request CI, a read-only or no-token baseline reduces the impact of unexpected token access. For privileged pull-request metadata work, the workflow should show exactly why a write scope exists and should avoid running code from the pull request.
A first audit can start with five searches
Search workflow YAML for `permissions:`, `write-all`, `secrets.GITHUB_TOKEN`, `github.token`, and `pull_request_target`. Those strings map to the source-backed review areas in this guide: explicit token scope, broad write grants, implicit token access, and privileged pull-request automation. [1] [2]
For a local review queue, run gha-guard against the repository and inspect any token-permissions, trigger, checkout, timeout, or shell-context findings before merging workflow changes.
This article is informational and is not a substitute for a security review of your own workflows, repositories, or cloud accounts.
CI Tripwire has not commissioned independent expert review of this article. Read more about the organization byline at contributors and the source posture at sourcing.
Corrections can be routed through the corrections note. Sources: 4 entries, primary platform, security reference, and project documentation, last reviewed 2026-06-07.
Sources
- GitHub Docs, Use GITHUB_TOKEN for authentication in workflows.
- GitHub Docs, Workflow syntax for GitHub Actions.
- GitHub Docs, Secure use reference.
- OpenSSF Scorecard, checks documentation: Token-Permissions.