PermissionsThu May 07 2026 00:00:00 GMT+0000 (Coordinated Universal Time)

How to Scope GitHub Actions Permissions Without Breaking CI

Most workflows do not need broad write access. This guide shows how to trim GitHub Actions permissions step by step.

How to Scope GitHub Actions Permissions Without Breaking CI
action pin team

One of the most useful GitHub Actions security improvements is also one of the easiest to delay: reducing token permissions.

Teams avoid it because they assume something will break. Sometimes it does. The fix is not to keep broad write access everywhere. The fix is to scope access with intent.

Start with the default question

For every workflow, ask:

What does this job actually need to do?

Common answers:

  • read repository contents
  • comment on a pull request
  • update a commit status
  • publish a package
  • create a release
  • deploy to an environment

Those are different access patterns. They should not all share the same token scope.

Use top-level permissions as a floor, not a shortcut

A good baseline is:

permissions:
  contents: read

Then grant stronger permissions only in the job that needs them:

jobs:
  release:
    permissions:
      contents: write
      packages: write

This prevents a test job, lint job, or analysis job from inheriting write access by default.

Watch for hidden write paths

Some workflows need write access indirectly because they:

  • create pull requests
  • push version bumps
  • upload packages
  • write deployment statuses
  • comment on issues or PRs

The answer is not to allow write-all. The answer is to identify the exact scope and confine it to the relevant job.

Common permission mistakes

write-all as a convenience setting

This is fast during setup and expensive later. It makes review harder because nobody can tell which step actually needs privilege.

Using one workflow for both untrusted and privileged paths

If a workflow runs on pull requests from forks and also needs write access, split the concerns. Keep the untrusted path read-only and move privileged operations elsewhere.

Forgetting repository-level defaults

Even if a workflow looks minimal, repository defaults may still be broader than expected. Review both the workflow file and the repository or organization settings.

A rollout plan that avoids breakage

If your team has many workflows, do not tighten everything at once. Use a staged rollout:

  1. Set contents: read in low-risk workflows.
  2. Move required write permissions to specific jobs.
  3. Test release and automation paths.
  4. Block new workflows that introduce broad permissions without justification.

This gives you fast wins without creating a migration freeze.

When write permissions are justified

Write scopes are not bad by themselves. They are bad when they are vague, inherited broadly, or mixed into untrusted execution paths.

Legitimate examples include:

  • release publishing
  • changelog automation
  • labeling and triage bots
  • deployment status updates

The goal is explicit access, not zero access.

The standard to aim for

A healthy GitHub Actions permissions model is simple:

  • most workflows are read-only
  • privileged jobs are obvious in review
  • high-risk triggers are isolated
  • engineers can explain why each write scope exists

That is enough to reduce a large class of GitHub workflow security issues before you ever reach enterprise-scale tooling.

From guide to guardrail

Apply this checklist to your repositories

Use action pin to find unpinned actions, broad token permissions, risky pull request triggers, and workflow security issues before they merge.

Scan GitHub Actions

Related Guides

Keep hardening GitHub Actions

Learn the GitHub Actions security best practices that reduce supply-chain risk without turning your small team into a DevSecOps department.

A practical rollout plan for SHA pinning in GitHub Actions, including what to pin first and how to handle updates safely.

Understand the real risk behind pull_request_target and how to separate untrusted pull request code from privileged automation.