Skip to content

Grant least-privilege CI permissions at both workflow and job level

This is a principle

A reusable technical claim: something I would want true in any of my work.

Claim. Declare the minimum token permissions a workflow needs, explicitly - set a restrictive baseline at the workflow level, then narrow (or selectively elevate) per job, so each job holds only what it actually uses.

When to apply. Any CI system with scoped tokens (GitHub Actions permissions, etc.). Broadly applicable.

Why. CI tokens run with whatever scope you grant; the platform default is often far broader than needed, so a compromised action or dependency in any job inherits write access to your repo, releases or pages. Setting a tight workflow-level baseline and granting elevated scopes to only the one job that needs them (e.g. the deploy job gets pages: write/id-token: write, everything else stays read-only) contains blast radius. Prefer OIDC (id-token) over long-lived stored secrets where the platform supports it.

Snippet.

permissions:            # workflow-level baseline: minimal
  contents: read
jobs:
  deploy:
    permissions:        # only this job elevates
      pages: write
      id-token: write

How enforced. Explicit permissions: blocks at both levels; no reliance on inherited defaults. Related: Pin GitHub Actions to full commit SHAs (same supply-chain threat model).

The following pages link to this page: