Skip to content
Latchkey

Least-Privilege Permissions for GITHUB_TOKEN

Every workflow gets a powerful token by default; most of that power is unnecessary.

GitHub Actions injects an automatic GITHUB_TOKEN into every workflow. By default it can be broad, and a compromised action or dependency runs with whatever that token can do. The fix is least privilege: start read-only and grant exactly the scopes each job needs. This lesson shows how.

What GITHUB_TOKEN is

The GITHUB_TOKEN is a short-lived token GitHub creates per workflow run to interact with your repository: checking out code, posting statuses, publishing packages. It expires when the run ends, but during the run it is a real credential, so its scope matters.

Default to read-only

Set a restrictive default at the top of the workflow, then widen only where needed. Many workflows need nothing more than contents: read.

.github/workflows/ci.yml
permissions:
  contents: read

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci && npm test

Grant scopes per job

Override permissions on the specific job that needs more, keeping the broad default narrow. Here only the publish job gets packages: write.

.github/workflows/release.yml
jobs:
  publish:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    steps:
      - run: ./publish.sh

Why it matters

  • A compromised third-party action runs with your token's permissions; a read-only token cannot push or publish.
  • Per-job scoping limits the blast radius to the one job that truly needs elevated access.
  • Setting an org-wide read-only default for GITHUB_TOKEN makes least privilege the safe default everywhere.

Key takeaways

  • Set a permissions: contents: read default and widen only where a job needs it.
  • Grant elevated scopes (like packages: write) on the specific job, not workflow-wide.
  • A least-privilege token limits the damage a compromised action or dependency can do.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →