Lesson 16 / 25
GITHUB_TOKEN Permissions
Least privilege per workflow and job.
Declare what the token may do
Each run gets an automatic GITHUB_TOKEN scoped to the repository. Set permissions: at the workflow or job level to the minimum needed (contents: read for CI; add pull-requests: write to comment, packages: write to publish, id-token: write for OIDC). Once you specify any permission, unspecified scopes become none. Set the organisation or repository default to read-only so new workflows start safe. Scope names are checked by actionlint, as the earlier lint showed for pull-request versus pull-requests.
Least privilege, untrusted input, pinned dependencies
Workflows hold credentials and run code; treat them as production infrastructure.
Minimal permissions per job
Not linted or run here; check the GitHub Actions documentation for current syntax.
permissions:
contents: read # default for every job in this workflow
jobs:
test:
runs-on: ubuntu-latest
steps: [ { uses: actions/checkout@v4 }, { run: npm test } ]
comment:
needs: test
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write # only this job may comment
steps: [ { run: gh pr comment "$PR" --body "Tests passed" } ]Default the org to read-only
Organisation settings can make the token read-only by default, forcing workflows to request write access explicitly.
Quick check: What happens to unspecified scopes once you set permissions:?
- They keep the repository default
- They become write
- They are set to none
- The workflow fails to start
Answer
They are set to none — Explicit allow-list.