# The problem
The automatic token is convenient, and convenience means it usually carries more access than the job needs. A compromised dependency or a malicious step then inherits all of it. The fix is boring and effective: declare exactly what each job may do.

# The pattern
Put a permissions block on every job with only the scopes it needs:
permissions:
  contents: read
A job that opens issues adds issues write. A job that only runs tests gets contents read and nothing else. When a job needs nothing from the API, say so explicitly rather than inheriting the default.

# Why per job, not per workflow
Different jobs do different things. A workflow-level grant is the union of what every job needs, which is the maximum, not the minimum. Per-job scoping keeps a breach in one job from becoming a breach of everything.

# Checks
- Every job in every workflow should carry an explicit permissions block. No block means it inherits the broad default.
- When adding a permission, ask whether the job really needs write or whether read suffices. Read is almost always enough.