Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .github/workflows/autofix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@ on:
pull_request_review_comment:
types: [created]

permissions: {}
# The reusable's GITHUB_TOKEN is capped by these grants: marker comments
# (issues: write), PR reads (pull-requests: read), and the no-app push
# fallback (contents: write). Owner-approved 2026-10-21.
permissions:
contents: write
pull-requests: read
issues: write
Comment thread
swu-rob[bot] marked this conversation as resolved.
Resolved

concurrency:
group: pr-autofix-${{ github.repository }}-${{ github.event.issue.number || github.event.pull_request.number }}
Expand Down
6 changes: 5 additions & 1 deletion scripts/autofix-workflows.node-test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,11 @@ test("PR Autofix is not pinned to a reusable revision that deadlocks", () => {

test("autofix callers keep their least-privilege and fork guards", () => {
const autofix = read(".github/workflows/autofix.yml");
assert.match(autofix, /^permissions: \{\}\s*$/m, "autofix.yml grants nothing at workflow level");
// Workflow-level grants are exactly the owner-approved caller grants
// (owner 2026-10-21, re-approved 2026-11-10 for PR #1644): the reusable's
// GITHUB_TOKEN is capped by these, and any other workflow-level permission
// added to autofix.yml must update this guard in the same change.
assert.match(autofix, /^permissions:\n {2}contents: write\n {2}pull-requests: read\n {2}issues: write\s*$/m, "autofix.yml workflow-level grants are exactly the approved caller grants");
Comment thread
swu-rob[bot] marked this conversation as resolved.
Resolved
assert.match(autofix, /^ {6}contents: write\n {6}pull-requests: read\n/m);
// The caller delegates identity enforcement to the pinned reusable. Its
// local gate must still control invocation and reject closed/non-PR events.
Expand Down
Loading