The default token permissions in an older repository are write-all, which means every third-party action in every job can push to the default branch.
# repository default, set once
permissions:
contents: read
# and per job, where more is genuinely needed
jobs:
release:
permissions:
contents: write # to create the tag
packages: write # to push the image
id-token: write # for OIDC
steps: ...
The blast radius argument is the one that lands: a compromised action in a lint job has no business being able to write to the repository, and the fix is one line at the workflow level. Turning the repository default to read-only broke two workflows immediately, both of which needed exactly one additional scope, which is a good ratio and the reason to do it in a quiet week.