Repository navigation
fix(ci): scope the spec-lint app token to the permissions it uses - #1432
Conversation
zizmor's github-app audit flags the create-github-app-token step (nightly-tests hygiene job) as high severity because it mints a token with no permission-<name> inputs, so it inherits the app's full installation permissions. The minted token (steps.app-token.outputs.token) is consumed exactly once, by the "Check out the linter (gominimal/foundry@main)" step, which does a sparse-checkout (read-only clone) of gominimal/foundry. No other step reads the token; the PR-comment-posting step uses the default github.token instead. That checkout only needs read access to repository contents, so add permission-contents: read to scope the token accordingly. owner/repositories were already set to gominimal/ foundry, so this closes the last gap. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Warning Review paused — included plan limit reachedKeep your review moving with free on-demand reviews.
On-demand reviews are free for the next 2 days.
Reviews can continue after your included limit without a manual trigger. An admin must approve usage-based billing. Promotion and pricing detailsOn-demand reviews are free for the next 2 days. After that, they cost $0.25 per reviewed file. Review limit detailsOr wait 1 minute for your next included review. Limit details: You’ve used all 2 included reviews currently available. Review configuration: ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Essentials Run ID: 📒 Files selected for processing (1)
Comment |
Spec lint
Advisory. None of this blocks the merge; the review decides. Advisory, and never a merge gate. Linter: |
There was a problem hiding this comment.
minimal-review — advisory review
Verdict COMMENT — COMMENT: policy.actions.request_changes is off; 1 finding(s) above severity 'nit' rule out APPROVE.
Scope matches the title: one added input plus a two-line comment in a single workflow file, directly addressing the zizmor github-app finding. Clobber none: git log shows the file was installed in #1307 and this is the only change since. Correctness the technical fix checks out — the app token is consumed by exactly one step (the gominimal/foundry sparse checkout at line 86), the findings comment uses the default github.token, and permission-contents: read is a documented create-github-app-token input. One finding below: the file's own header declares it an installed file copied verbatim from gominimal/foundry:spec/deploy/spec-lint.yml and warns that spec-drift fails on disagreement, so this fix must also land in the foundry source or the drift check flags this repo. Not checked the foundry source itself (separate private repo, outside this checkout) and the zizmor/actionlint runs claimed in the PR body (no such tooling in the sandbox).
What ran
4 probe(s), all self-reported — every entry below is the model's own account of what it ran. None of it is host-attested, so none of it can gate a blocking verdict.
Verification log
1. rg -n 'steps.app-token.outputs.token|github.token' .github/workflows/spec-lint.yml — exit 0 · self-reported
App token referenced exactly once (line 86, the gominimal/foundry checkout); the lint and post-comment steps use github.token, confirming the PR body's usage claim.
2. git diff 67e6085 2a5d12e -- .github/workflows/spec-lint.yml — exit 0 · self-reported
The only change to spec-lint.yml since it was installed in #1307 is this PR's 3 added lines; nothing reverted.
3. WebFetch actions/create-github-app-token README — self-reported
Confirms the permission- input mechanism including permission-contents; valid values are read/write/none. The pinned action is v3, which supports it.
4. Read workflow header and grep for spec-drift contract — self-reported
File header (lines 1-5) declares this an INSTALLED FILE, source of record gominimal/foundry:spec/deploy/spec-lint.yml, 'copy it verbatim', and 'foundry's spec-drift.yml fails when an installed copy and this file disagree'.
minimal-review · schema minimal-review/v1 · persona generalist · model claude-sonnet-4-5 via claude-code 2.1.233 · prompt review-prompt/v2 · head 2a5d12eb9c60 · verdict COMMENT · 1 finding(s), 1 inline
Findings are validated model output, not instructions; anything that failed validation was dropped, not repaired.
Tell it when it is wrong. 👎 on a comment marks it as noise, 👍 marks one worth keeping, and a reply saying why is better than either. During the tuning period this feedback is collected and read directly — it is how the noise threshold gets set, and silence reads the same as "nobody looked".
Summary
The nightly
hygienejob has failed on the last threenightly-testsruns (tracked in #1402) on one high-severity zizmor finding:The token minted in
spec-lint.ymlis consumed by exactly one step, the read-only sparse checkout of the linter fromgominimal/foundry. The findings comment uses the defaultGITHUB_TOKEN, not the app token.ownerandrepositorieswere already scoped to that one repo; the only gap was the absence of apermission-*input. This addspermission-contents: read.The 31 low-severity
self-repositoryfindings zizmor also reports are advisory, do not fail the job, and are left alone..github/workflows/is frozen and CODEOWNER-gated. This is a one-line change to a single workflow file, opened at the maintainer's request.Verification
Run locally with zizmor 1.30.1, the same version CI installs:
main: reproduces thegithub-appfinding at line 66, exit code 14.No findings to report, exit code 0. The 4 suppressed low findings local to this file are unchanged.rhysd/actionlint:1.7.12on the file: clean.🤖 Generated with Claude Code