ci: give every workflow a least-privilege GITHUB_TOKEN - #918
Merged
Merged
Conversation
Fixes the Scorecard Token-Permissions check, which scored 0 because six
workflows declared no top-level permissions and so inherited whatever the
repository default grants:
engine-benchmarks.yml, java-tests.yml, native-cpu-multiarch.yml,
publish.yml, schema-validation.yml, verify-poms.yml
All six now follow the pattern build.yml and reuse-compliance.yml already
used: top-level `permissions: {}`, with each job granted only what it needs.
Every one of them is read-only CI -- checkout, setup-java, cache and
upload-artifact -- so `contents: read` is the whole requirement.
upload-artifact authenticates with the Actions runtime token rather than
GITHUB_TOKEN, and publish.yml reaches Maven Central and GPG through
repository secrets, which are independent of GITHUB_TOKEN, so nothing here
loses access it was using.
Also moved two top-level write grants down to the single job that needs
them, which is the other half of what this check penalises:
docs.yml pages/id-token write reached build-docs as well as
deploy-docs; only deploy-pages needs them
documentation.yml pull-requests write reached build-documentation as
well as preview-documentation; only the github-script
comment step needs it
No workflow now holds a write permission at top level, and no job holds a
permission it does not exercise.
|
📖 Documentation Preview The documentation has been built successfully for this PR. Generated Files:
Artifacts:
This comment will be updated automatically when the PR is updated. |
aharakal
approved these changes
Aug 9, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes the OpenSSF Scorecard Token-Permissions check (currently scoring 0/10, severity high), and the matching
TokenPermissionsIDcode-scanning alerts.The reported problem
Six workflows declared no top-level
permissions, so they inherited whatever the repository default grants — historically read/write on everything:All six now follow the pattern
build.ymlandreuse-compliance.ymlalready used — top-levelpermissions: {}with per-job grants — so this introduces no new convention.What each workflow actually needs
Every one of the six is read-only CI:
checkout,setup-java,cache,upload-artifact.contents: readis the entire requirement.Two cases that look like they need more but do not:
upload-artifact/download-artifactauthenticate with the Actions runtime token (ACTIONS_RUNTIME_TOKEN), notGITHUB_TOKEN. Restrictingpermissionsdoes not affect them.publish.ymlreaches Maven Central and GPG throughsecrets.MAVEN_CENTRAL_*/secrets.GPG_PRIVATE_KEY/secrets.SIGNING_PASSWORD. Repository secrets are independent ofGITHUB_TOKENpermissions, and the workflow creates no GitHub Release, so it needs no write access to the repository itself.Also: two top-level write grants moved down
This is the other half of what the check penalises — a top-level write reaches every job in the file, not just the one that needs it.
docs.ymlpages: write+id-token: write, reachingbuild-docstoodeploy-docsonly;build-docsgetscontents: readdocumentation.ymlpull-requests: write, reachingbuild-documentationtoopreview-documentationonly;build-documentationgetscontents: readbuild-docsonly checks out and uploads a Pages artifact —actions/upload-pages-artifactdoes not needpages: write(there is noconfigure-pagesstep in this workflow).deploy-docsrunsactions/deploy-pages, which needspages: writeto publish andid-token: writefor the OIDC exchange, and never checks the repository out.Result
Every workflow now has a top-level permission block, none holds a write at top level, and no job holds a permission it does not exercise:
{}contents: read; build-job none{}contents: read; deploy-docspages: write,id-token: write{}contents: read; previewcontents: read,pull-requests: write{}contents: read{}contents: read{}contents: read{}security-events: write){}contents: read{}contents: read{}contents: read{}contents: readVerification and its limits
All 11 files parse, and a script asserts every workflow has a top-level block, no top-level write, and every job's grants are declared.
Two paths this PR's CI cannot exercise, and a reviewer should know that:
publish.ymlonly triggers on tag push. The reasoning above (secrets are independent ofGITHUB_TOKEN; no Release is created) is sound, but it is unproven until the next release tag.docs.yml'sdeploy-docsonly triggers on a published release, so the Pages deploy is likewise untested here.Everything else — build, java-tests, verify-poms, schema-validation, native-cpu-multiarch, reuse-compliance, documentation — runs on this PR and is proven by its own checks.