← Back to articles

CI/CD · Token Permissions

GitHub Actions: Give Each Job Only the Token Permissions It Needs

Use explicit workflow and job permissions to keep verification and release capabilities aligned with their tasks.

A cyan key branches toward a blue inspection station and a gated emerald release station.
Different CI jobs need different capabilities.

A test job and a release job perform different work. Their GitHub tokens should reflect that difference instead of sharing broad write access.

Start with a small permission set

Declare permissions at workflow or job level. For a test job that reads repository files, a useful starting point is:

permissions:
  contents: read

When you specify individual permissions, unspecified permissions become none. Check every action in the job before tightening access; a reporting step may need an additional capability.

Give publishing its own boundary

Keep release operations in a separate job and explicitly grant the capabilities that operation needs. For example, publishing a repository release may require contents: write. Repeat any read permissions that job also needs rather than assuming an unspecified permission remains available.

Remember implicit token access

An action can access github.token even when no token input appears in its step configuration. Omitting a token argument therefore does not establish a permission boundary; the permissions declaration does.

Review with a concrete scenario

Imagine a dependency-installation step behaving unexpectedly. Ask which repository operations its job token could perform. Keep ordinary verification jobs narrow, review failures for the missing capability, and grant that capability only where the intended operation requires it.