github/workflows: add scoped permissions blocks#5967
Open
eriknordmark wants to merge 5 commits into
Open
Conversation
zizmor's artipacked audit warns that actions/checkout writes GITHUB_TOKEN into .git/config by default, which can be exfiltrated by a later step that uploads the workspace as an artifact. Set persist-credentials: false on every checkout so the token is discarded immediately after the clone. The exception is build-alpine-base.yml's commit-hash job, which pushes the updated alpine-base image hash back to master and needs the token to remain. Mark that checkout with an inline zizmor ignore plus a comment explaining the dependency. Signed-off-by: eriknordmark <erik@zededa.com> Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
actionlint (run via reviewdog with reporter: github-check) flags any
${{ github.event.pull_request.head.* }} or ${{ github.event.comment.body }}
expression interpolated directly into a run: script because the PR
branch name and comment body are attacker-influenced.
Move HEAD_SHA, HEAD_REF, and BODY into step env: blocks in
ascii-check.yml, commit-messages.yml, request_codeowners_review.yml,
rerun-ci.yml, and spdx.yml. The shell scripts now read "$HEAD_SHA",
"$HEAD_REF", "$BODY" — the values are still attacker-influenced but
shell quoting prevents script injection.
Also quote the reviewers_array expansion in
request_codeowners_review.yml so shellcheck SC2068 stops firing.
Signed-off-by: eriknordmark <erik@zededa.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
A composite action's inputs metadata only accepts name, description, required, default, and deprecationMessage; the type key is reserved for reusable-workflow inputs (workflow_call). actionlint correctly rejects "type: string" and "type: boolean" here, which has been failing the Workflow Lint job on every PR touching .github/workflows. Strip the type keys. The clean default switches from the YAML boolean true to the string 'true' so the unchanged inputs.clean == 'true' comparison in this file still resolves the same way; the only existing caller that overrides clean uses clean: false (publish.yml), which coerces to the string "false" exactly as before. Signed-off-by: eriknordmark <erik@zededa.com> Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Open
7 tasks
reviewdog/action-actionlint submits every shellcheck finding as a separate GitHub annotation, including info-level ones. PRs that touch enough workflow files push reviewdog past GitHub's per-check annotation cap and the Workflow Lint job fails on "Too many results (annotations) in diff" rather than on an actual finding. The level input on the action only sets a default severity for findings that don't carry their own; it does not filter the stream. Pass actionlint_flags so shellcheck stops emitting SC2086, SC2046, and SC2035 entirely (boilerplate quoting and glob suggestions that were the bulk of the noise). All actionlint rules and any error-level shellcheck rules still run. Signed-off-by: eriknordmark <erik@zededa.com> Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
242b06d to
6e7fe3f
Compare
The GITHUB_TOKEN handed to a job inherits whichever scope the
repository default grants when a workflow does not declare its own
permissions:. zizmor's excessive-permissions audit flags every job
that runs under that wider default. Add a least-privilege
permissions: block to each workflow that lacked one.
Most workflows only read the repo and call out to external services
(DockerHub, codecov, …) with their own secrets — contents: read at
the top level is enough. The exceptions:
- close-master-pr.yml uses pull_request_target to close PRs from
master and post an explainer comment, so it gets
pull-requests: write and issues: write at the job level over a
permissions: {} workflow default.
- cve-scan.yml delegates to shjala/eve-cvewatch's reusable scanner;
pass contents: read to the callee, deny everything else.
- pr-gate.yml's eden-gate job uses gh CLI to read PR review state
and the upstream build run; grant actions: read and
pull-requests: read over a permissions: {} default.
- eden-trusted.yml previously set statuses: write workflow-wide;
move that to status_ui, finalize, and subjob_statuses, which are
the only jobs that actually write commit statuses.
- osv-scanner.yml previously set security-events: write
workflow-wide; move to per-job alongside actions: read and
contents: read for the two reusable-workflow callers.
Signed-off-by: eriknordmark <erik@zededa.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
6e7fe3f to
86e3a5e
Compare
rene
reviewed
May 18, 2026
| inputs: | ||
| command: | ||
| required: true | ||
| type: string |
Contributor
There was a problem hiding this comment.
What is the reason to remove type?
rene
reviewed
May 18, 2026
| with: | ||
| reporter: github-check | ||
| fail_level: error | ||
| # Silence shellcheck info/warning codes that produce |
Contributor
There was a problem hiding this comment.
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.
Description
zizmor's
excessive-permissionsaudit fires on every job whoseGITHUB_TOKEN scope is whatever the repository default grants (typically
broader than the job needs). Add a least-privilege
permissions:blockto each workflow that lacked one.
Most workflows only read the repo and call out to external services
(DockerHub, codecov, …) with their own secrets, so
contents: readatthe top level is enough. The exceptions:
close-master-pr.ymlusespull_request_targetto close PRs andpost an explainer comment, so it gets
pull-requests: writeandissues: writeat the job level over apermissions: {}workflowdefault.
cve-scan.ymldelegates toshjala/eve-cvewatch's reusable scanner;pass
contents: readto the callee and deny everything else.pr-gate.yml'seden-gatejob usesghCLI to read PR reviewstate and the upstream build run; grant
actions: readandpull-requests: readoverpermissions: {}.eden-trusted.ymlpreviously setstatuses: writeworkflow-wide;move that to
status_ui,finalize, andsubjob_statuses, thethree jobs that actually write commit statuses.
osv-scanner.ymlpreviously setsecurity-events: writeworkflow-wide; move to per-job alongside
actions: readandcontents: readfor the two reusable-workflow callers.PR dependencies
Depends on #5966. That PR carries the
artipackedandtemplate-injection-error fixes for the same workflow files, plus asmall actionlint config adjustment that lets the Workflow Lint job
stay green when many workflows are touched in one PR. The three
commits at the bottom of this branch are #5966; rebase out after it
merges.
How to test and validate this PR
excessive-permissionsfindings.auto_request_reviewjob (run byrequest_codeowners_review.yml) still posts reviewers — it now runsunder the explicit
permissions: pull-requests: writeblock that'salready in master.
eden-trusted.yml:status_ui,finalize, andsubjob_statusesmust still successfully write commit statuses on the PR head SHA
under their per-job
statuses: write.reusable-workflow callers must still upload SARIF.
Changelog notes
None. CI hardening only.
PR Backports
Checklist