Skip to content

ci: give every workflow a least-privilege GITHUB_TOKEN - #918

Merged
michalharakal merged 1 commit into
developfrom
ci/workflow-token-permissions
Aug 9, 2026
Merged

michalharakal merged 1 commit into
developfrom
ci/workflow-token-permissions

Conversation

@michalharakal

Copy link
Copy Markdown
Contributor

Fixes the OpenSSF Scorecard Token-Permissions check (currently scoring 0/10, severity high), and the matching TokenPermissionsID code-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:

Warn: no topLevel permission defined: .github/workflows/engine-benchmarks.yml:1
Warn: no topLevel permission defined: .github/workflows/java-tests.yml:1
Warn: no topLevel permission defined: .github/workflows/native-cpu-multiarch.yml:1
Warn: no topLevel permission defined: .github/workflows/publish.yml:1
Warn: no topLevel permission defined: .github/workflows/schema-validation.yml:1
Warn: no topLevel permission defined: .github/workflows/verify-poms.yml:1

All six now follow the pattern build.yml and reuse-compliance.yml already used — top-level permissions: {} 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: read is the entire requirement.

Two cases that look like they need more but do not:

  • upload-artifact / download-artifact authenticate with the Actions runtime token (ACTIONS_RUNTIME_TOKEN), not GITHUB_TOKEN. Restricting permissions does not affect them.
  • publish.yml reaches Maven Central and GPG through secrets.MAVEN_CENTRAL_* / secrets.GPG_PRIVATE_KEY / secrets.SIGNING_PASSWORD. Repository secrets are independent of GITHUB_TOKEN permissions, 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.

Workflow Was Now
docs.yml top-level pages: write + id-token: write, reaching build-docs too on deploy-docs only; build-docs gets contents: read
documentation.yml top-level pull-requests: write, reaching build-documentation too on preview-documentation only; build-documentation gets contents: read

build-docs only checks out and uploads a Pages artifact — actions/upload-pages-artifact does not need pages: write (there is no configure-pages step in this workflow). deploy-docs runs actions/deploy-pages, which needs pages: write to publish and id-token: write for 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:

Workflow Top Job grants
build.yml {} test / assemble contents: read; build-job none
docs.yml {} build-docs contents: read; deploy-docs pages: write, id-token: write
documentation.yml {} build contents: read; preview contents: read, pull-requests: write
engine-benchmarks.yml {} both jobs contents: read
java-tests.yml {} contents: read
native-cpu-multiarch.yml {} contents: read
openssf-scorecard.yml {} unchanged (needs security-events: write)
publish.yml {} both jobs contents: read
reuse-compliance.yml {} contents: read
schema-validation.yml {} contents: read
verify-poms.yml {} contents: read

Verification 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.yml only triggers on tag push. The reasoning above (secrets are independent of GITHUB_TOKEN; no Release is created) is sound, but it is unproven until the next release tag.
  • docs.yml's deploy-docs only 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.

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.
@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown

📖 Documentation Preview

The documentation has been built successfully for this PR.

Generated Files:

  • Operator documentation: docs/modules/operators/_generated_/
  • JSON schema output: operators.json

Artifacts:

  • Download the documentation-preview-918 artifact to view the complete documentation locally.

This comment will be updated automatically when the PR is updated.

@michalharakal
michalharakal requested a review from aharakal August 9, 2026 19:00
@michalharakal
michalharakal merged commit 175d6fb into develop Aug 9, 2026
21 checks passed
@michalharakal
michalharakal deleted the ci/workflow-token-permissions branch August 9, 2026 19:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants