Skip to content

ci: declare workflow-level contents: read on 8 build/test workflows#4527

Open
arpitjain099 wants to merge 2 commits into
redis:masterfrom
arpitjain099:chore/declare-workflow-perms-readonly
Open

ci: declare workflow-level contents: read on 8 build/test workflows#4527
arpitjain099 wants to merge 2 commits into
redis:masterfrom
arpitjain099:chore/declare-workflow-perms-readonly

Conversation

@arpitjain099
Copy link
Copy Markdown

@arpitjain099 arpitjain099 commented May 14, 2026

Pins the default GITHUB_TOKEN to contents: read on the 8 workflows in .github/workflows/ that don't actually need any write scope:

  • benchmarks.yml: scheduled JMH benchmarks.
  • doctests.yml: jbang doctest runner.
  • format_check.yml: pmd / formatter checks.
  • integration.yml: redis integration test matrix.
  • snapshot.yml: snapshot deploy precheck. The actual Sonatype deploy uses a separate secret, not GITHUB_TOKEN.
  • spring-data-redis-integration.yml: spring-data-redis sanity check.
  • test-on-docker.yml: docker-based redis matrix.
  • unit-tests.yml: junit run.

None call a GitHub API beyond the initial checkout.

release-drafter.yml and version-and-release.yml are intentionally left implicit since they need write scopes; those are best declared by maintainers who own the release flow.

Why

CVE-2025-30066 (March 2025 tj-actions/changed-files supply-chain compromise) exfiltrated GITHUB_TOKEN from workflow logs and the leaked token retained whatever scope was issued at the workflow level. Pinning per workflow caps that runtime authority irrespective of the repo or org default, gives drift protection if the default ever widens, and is credited per-file by the OpenSSF Scorecard Token-Permissions check.

YAML validated locally with yaml.safe_load on each touched file.


Note

Low Risk
Low risk: only tightens GitHub Actions GITHUB_TOKEN permissions to read-only for workflows that just check out and run builds/tests, reducing blast radius without changing build logic.

Overview
Adds workflow-level permissions: contents: read to multiple CI workflows (e.g. benchmarks.yml, doctests.yml, format_check.yml, integration.yml, snapshot.yml, spring-data-redis-integration.yml, test-on-docker.yml).

This explicitly limits the default GITHUB_TOKEN to read-only for these jobs, reducing exposure from token leakage while leaving the workflows’ steps and triggers otherwise unchanged.

Reviewed by Cursor Bugbot for commit b2c9f48. Bugbot is set up for automated code reviews on this repo. Configure here.

Pins the default GITHUB_TOKEN to contents: read on the 8 workflows in
.github/workflows/ that don't actually need any write scope:

- benchmarks.yml: scheduled JMH benchmarks.
- doctests.yml: jbang doctest runner.
- format_check.yml: pmd / formatter checks.
- integration.yml: redis integration test matrix.
- snapshot.yml: snapshot deploy precheck (the actual deploy uses
  a separate Sonatype secret, not GITHUB_TOKEN).
- spring-data-redis-integration.yml: spring-data-redis sanity check.
- test-on-docker.yml: docker-based redis matrix.
- unit-tests.yml: junit run.

release-drafter.yml and version-and-release.yml are intentionally
left implicit since they need write scopes.

Motivation: CVE-2025-30066 (March 2025 tj-actions/changed-files
compromise) exfiltrated GITHUB_TOKEN from workflow logs. Per-workflow
caps bound runtime authority irrespective of repo or org default,
give drift protection if the default ever widens, and are credited
per-file by the OpenSSF Scorecard Token-Permissions check.

YAML validated locally with yaml.safe_load.

Signed-off-by: Arpit Jain <arpitjain099@gmail.com>
Comment thread .github/workflows/unit-tests.yml Outdated
@ggivo ggivo added the waiting-for-triage Still needs to be triaged label May 15, 2026
@ggivo
Copy link
Copy Markdown
Collaborator

ggivo commented May 15, 2026

Thanks — makes sense.

Before merging, we'll need to sanity-check that none of the flows rely on a write scope. One concrete flag: unit-tests.yml uses EnricoMi/publish-unit-test-result-action@v2.

Per @ggivo's review: unit-tests.yml uses EnricoMi/publish-unit-test-result-action@v2,
which writes test results back to the PR (needs pull-requests: write + checks: write).
Plain contents: read would break it, so leaving that file out of this PR for a
maintainer-driven follow-up that declares the right write scopes.

Signed-off-by: Arpit Jain <arpitjain099@gmail.com>
@arpitjain099
Copy link
Copy Markdown
Author

Thanks for the catch @ggivo, you're right. EnricoMi/publish-unit-test-result-action@v2 writes test results back to the PR (it needs pull-requests: write and checks: write to do that). Plain contents: read would break it.

Dropped unit-tests.yml from this PR. The 7 remaining files now in the diff (benchmarks.yml, doctests.yml, format_check.yml, integration.yml, snapshot.yml, spring-data-redis-integration.yml, test-on-docker.yml) really are read-only with respect to GITHUB_TOKEN. The unit-tests.yml permissions are best declared by a maintainer who can pin the exact write scopes the action needs.

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Reviewed by Cursor Bugbot for commit b2c9f48. Configure here.

default: ''

permissions:
contents: read
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Restricted permissions break test result publishing in workflow

High Severity

test-on-docker.yml is restricted to permissions: contents: read, but it invokes the .github/actions/run-tests composite action, which uses EnricoMi/publish-unit-test-result-action@v2 at line 172. This action requires checks: write and pull-requests: write to post test results. This is the same action that caused unit-tests.yml to be dropped from this PR, but the dependency through the composite action was missed.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit b2c9f48. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

waiting-for-triage Still needs to be triaged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants