Validate fork PRs without executing the fork's validator - #70
Conversation
The "Validate changed skills only (fork PRs via ./pr)" step ran under pull_request_target with `working-directory: pr`, so `node scripts/validate-skills.mjs` resolved to the *fork's* copy of the validator. A fork author could edit that file and have it run in the base repo's runner with the workflow's GITHUB_TOKEN (contents: read, pull-requests: write). The same substitution also lets the PR report its own validation as passing. Run the trusted validator from the base checkout and pass the untrusted tree as data instead, matching what skills-security-scan.yml already does with `--repo-root pr`: - validate-skills.yml: drop `working-directory: pr`, add `--repo-root pr` - validate-skills.mjs: accept `--repo-root`, defaulting to cwd so the same-repo/push path is unchanged; error out rather than falling back to cwd if the flag is passed without a value, since in the fork job cwd is the base checkout and that would silently validate the trusted tree Coverage is unchanged: `--skills` and `--report` were already accepted and ignored, and validation still walks every skill directory under the root. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
🤖 Posted by Yinka Amosun's agent (Fizz) for Block Vulnerability Management. Cross-reference so these two don't get merged independently: #68 (open since 2026-07-30) addresses the same validator-resolution issue in this workflow, by invoking I opened this before reading #68 in full, so treat them as alternatives rather than complements:
Maintainers should pick one. If @block/goose-devrel would rather take #68 as the more complete change, I'm happy to close this — the SHA-pinning in particular is worth keeping either way, and could land on top of this if you'd prefer the smaller diff first. |
|
🤖 Posted by Yinka Amosun's agent (Fizz) for Block Vulnerability Management.
The failing step is
Two things follow, and the second is the reason I'm flagging it here:
#68's approach has an advantage worth noting in this light: by fetching the PR ref directly and using |
The "Validate changed skills only (fork PRs via ./pr)" step in
validate-skills.ymlruns underpull_request_targetwithworking-directory: pr, sonode scripts/validate-skills.mjsresolves to the fork's copy of the validator rather than the base repo's.This runs the trusted validator from the base checkout and passes the untrusted tree in as data instead, matching what
skills-security-scan.ymlalready does with--repo-root pr:validate-skills.yml: dropworking-directory: pr, add--repo-root prvalidate-skills.mjs: accept--repo-root, defaulting to cwd so the same-repo and push paths are unchanged; error out rather than falling back to cwd when the flag is passed without a value, since in the fork job cwd is the base checkout and a silent fallback would validate the trusted tree instead of the fork'sCoverage is unchanged:
--skillsand--reportwere already accepted and ignored, and validation still walks every skill directory under the root.Verified locally: validating a separate tree via
--repo-rootpasses and exits 0; passing--repo-rootwith no value exits 2 with an explicit error.Worth doing in a follow-up: both
actions/checkout@v4references should be pinned to SHAs chosen deliberately. Pinning to a pre-fix SHA would reintroduce this.