ci: restrict default token permissions to read-only - #8440
Conversation
Without an explicit block, the automatic token inherits whatever the repository or organisation default grants, which can include write scopes. Neither workflow writes anything back to GitHub, so a compromised step or action had more reach than the work required. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Every job here authenticates through a GitHub App token, so the automatic token is never used: the write grant it carried could not authorise the pushes to the component repositories anyway, since its scope is limited to this repository. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
f66256f to
fd973c4
Compare
|
I went through the two objections that were raised against this PR. Both check out in your favour — I pushed nothing, the branch is good as it is. 1.
|
What
Declares a top-level
permissions: contents: readin the CI, Guides and Release Pipeline workflows.Commit Lintalready had one and is untouched.Nothing in the CI or Guides workflows writes back to GitHub — no
git push, noghcall, no PR-creating action. Artifact upload and dependency caching authenticate withACTIONS_RUNTIME_TOKEN, notGITHUB_TOKEN, so they are unaffected by the restriction.Release Pipeline does push: its subtree-split job runs
subtree.sh, which splits eachsrc/*component and pushes the result to the matching per-component repository. It nonetheless loses thecontents: writethat job declared, because that grant was never what authorised those pushes — every target is a separate repository (api-platform/serializer,api-platform/state, …), andGITHUB_TOKENis scoped to this repository alone, so no permission level on it could reach them. The credential that does authorise them is the GitHub App token, whichactions/checkoutreceives explicitly and stores as a host-scopedhttp.https://github.com/.extraheader, applying to the remotes the script adds afterwards. No step in the workflow referencesGITHUB_TOKENat all, so all three jobs run read-only and the release process is unchanged.Why
With no explicit block,
GITHUB_TOKENinherits the repository or organisation default, which on older settings is read and write across every scope. That is ambient authority these jobs never exercise: any compromised step, dependency or action in a run triggered from a branch push could use it to push commits, edit issues, or alter releases.Declaring the scopes makes the grant match the work, and also pins it against a future change to the org-wide default.
🤖 Generated with Claude Code