Skip to content

fix(workflows): declare the permissions these jobs' actions actually need - #497

Merged
prisis merged 1 commit into
mainfrom
fix/reusable-workflow-permissions
Sep 5, 2026
Merged

fix(workflows): declare the permissions these jobs' actions actually need#497
prisis merged 1 commit into
mainfrom
fix/reusable-workflow-permissions

Conversation

@prisis

@prisis prisis commented Sep 4, 2026

Copy link
Copy Markdown
Member

Three reusable-workflow jobs run an action that needs a scope the job never declares.

Consumers cannot work around any of these. A called workflow may only reduce the caller’s permissions, never raise them — so granting the scope on the calling job has no effect once the callee declares a narrower set.

file job missing action that needs it
lint.yml files-changed pull-requests: read dorny/paths-filter
zizmor.yml zizmor contents: read actions/checkout
set-default-labels.yml set-default-labels contents: read actions/checkout

lint.yml — files-changed

dorny/paths-filter does not diff git for a pull_request event; it calls GET /repos/{owner}/{repo}/pulls/{number}/files. The job declared no permissions of its own, so it inherited the workflow-level contents: read and the call came back:

##[error]Resource not accessible by integration

The job fails, every lint job downstream is skipped, and test-required-check exits 1 — so the check reports failure without a single linter having run.

zizmor.yml — zizmor

The job declared only security-events: write, so actions/checkout had no read scope. This is invisible on a public repo, where the clone succeeds unauthenticated anyway. On a private one git reports the repository as absent:

##[error]fatal: repository 'https://github.com/<owner>/<repo>/' not found

which reads as a wrong URL rather than a missing scope. zizmor then never produces results.sarif, so the upload step fails too.

set-default-labels.yml

Same shape as zizmor. Found by sweeping the rest of .github/workflows/ for the same class rather than waiting for it to be reported — it has not bitten yet because it is gated on github.repository == inputs.target-repo.

Verification

Read off the runner’s own GITHUB_TOKEN Permissions block on a private consumer, rather than inferred from the YAML:

# lint / Detect what files changed        # zizmor / Zizmor
Contents: read                            Metadata: read
Metadata: read                            SecurityEvents: write

In the first, the caller had granted pull-requests: read and it was silently dropped. After the change a re-run of the sweep reports every job declaring what its actions need, and all three files still parse.

Each addition is strictly a widening, so no existing consumer loses anything.

🤖 Generated with Claude Code

https://claude.ai/code/session_01GogDZZtdAedQLUrW4cAzLb

Summary by CodeRabbit

  • Bug Fixes
    • Improved automated workflow reliability by granting required read permissions for changed-file detection and repository checkout.
    • Prevented lint, labeling, and security checks from failing or skipping results due to insufficient access permissions.

…need

Three jobs run an action that needs a scope the job never declares. A consumer
cannot work around any of them: a called workflow may only REDUCE the caller's
permissions, never raise them, so granting the scope on the calling job has no
effect once the callee declares a narrower set.

**lint.yml / files-changed — `pull-requests: read`.** `dorny/paths-filter` does
not diff git for a `pull_request` event; it calls
`GET /repos/{owner}/{repo}/pulls/{number}/files`. The job declared no
`permissions` of its own, so it inherited the workflow-level `contents: read`
and the call came back `Resource not accessible by integration`. The job fails,
every lint job downstream is skipped, and `test-required-check` exits 1 — so the
whole check reports failure without a single linter having run.

**zizmor.yml / zizmor — `contents: read`.** The job declared only
`security-events: write`, so `actions/checkout` had no read scope. This is
invisible on a public repo, where the clone succeeds unauthenticated anyway. On
a private one git reports the repository as absent:

    fatal: repository 'https://github.com/<owner>/<repo>/' not found

which reads as a wrong URL rather than a missing scope. `zizmor` then never
produces `results.sarif`, so the upload step fails too.

**set-default-labels.yml — `contents: read`.** Same shape as zizmor: declares
`issues: write` and checks out without a read scope. Found by sweeping the rest
of the directory for the same class rather than waiting for it to be reported.

Verified against the runner's own `GITHUB_TOKEN Permissions` block on a private
consumer, which showed `Contents: read, Metadata: read` for the lint job (the
caller's `pull-requests: read` silently dropped) and `Metadata: read,
SecurityEvents: write` for zizmor.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GogDZZtdAedQLUrW4cAzLb
@coderabbitai

coderabbitai Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Team

Run ID: a79115a4-a1bb-4844-b59d-669390ddc268

📥 Commits

Reviewing files that changed from the base of the PR and between d05d9cb and 0201250.

📒 Files selected for processing (3)
  • .github/workflows/lint.yml
  • .github/workflows/set-default-labels.yml
  • .github/workflows/zizmor.yml

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The pull request adds explicit GitHub Actions read permissions. The lint workflow can read pull-request file lists. The label and zizmor workflows can check out private repositories.

Changes

Workflow permissions

Layer / File(s) Summary
Lint file detection permissions
.github/workflows/lint.yml
The files-changed job grants contents: read and pull-requests: read to support dorny/paths-filter.
Private repository checkout permissions
.github/workflows/set-default-labels.yml, .github/workflows/zizmor.yml
The jobs grant contents: read so actions/checkout can access private repositories.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: ⚪ Minimal · up to 02012

The workflows now grant the read access needed to detect pull-request files and check out private repositories, restoring lint, labeling, and zizmor execution without introducing an outstanding merge-readiness risk.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: updating workflow permissions to match the actions used by each job.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/reusable-workflow-permissions

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@prisis
prisis merged commit c25805b into main Sep 5, 2026
19 checks passed
@prisis
prisis deleted the fix/reusable-workflow-permissions branch September 5, 2026 08:50
prisis pushed a commit that referenced this pull request Sep 5, 2026
## [23.0.5](v23.0.4...v23.0.5) (2026-09-05)

### Bug Fixes

* **deps:** update github-actions ([#488](#488)) ([593b416](593b416))
* **deps:** update patch updates to ^8.10.1 ([#496](#496)) ([f0a80c6](f0a80c6))
* **workflows:** declare the permissions these jobs' actions actually need ([#497](#497)) ([c25805b](c25805b))
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.

1 participant