Repository navigation
Scope PR push file policy to agent commits - #67241
Conversation
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
|
🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅
|
|
✅ Test Quality Sentinel completed test quality analysis. Test Quality Sentinel skipped because pre-fetch PR data was unavailable: unable to fetch test file diff
|
|
✅ Ponytail Reviewer completed successfully! Lean already. Ship.
|
|
✅ Design Decision Gate 🏗️ completed the design decision gate check. See the comment below for the result and any generated ADR draft. No ADR enforcement needed for PR #67241: the PR does not carry the 'implementation' label and has 0 new lines in business logic directories (3 files changed, threshold 100).
|
|
✅ PR Code Quality Reviewer completed the code quality review. Testing whether safeoutputs write intents can be emitted without local file writes.
|
There was a problem hiding this comment.
🟡 Changes recommended
Merged upstream commits can still be misclassified as agent-owned, and changed-then-reverted coverage is incomplete.
2 open findings
What changed in this PR
Scopes PR push file-policy checks to agent-added commits after the existing PR head.
Changes:
- Uses the existing PR head as the allowlist baseline.
- Adds regressions for author-owned and agent-owned files.
- Verifies bundle file detection after an existing PR head.
| File | Description |
|---|---|
actions/setup/js/safe_outputs_handlers.cjs |
Implements incremental file-policy validation. |
actions/setup/js/safe_outputs_handlers.test.cjs |
Tests incremental allowlist behavior. |
actions/setup/js/push_to_pull_request_branch.integration.test.cjs |
Tests bundle file scoping. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
| } else { | ||
| const branchHistoryFiles = execGitSync(["log", "--name-only", "--pretty=format:", `origin/${baseBranch}..${pushPinnedSha}`, "--"], { cwd: pushGitCwd }) | ||
| const incrementalBase = prHeadBaseline?.sha || prHeadBaseline?.ref || `refs/remotes/origin/${entry.branch}`; | ||
| const agentFiles = execGitSync(["log", "--name-only", "--pretty=format:", `${incrementalBase}..${pushPinnedSha}`, "--"], { cwd: pushGitCwd }) |
There was a problem hiding this comment.
Updated the commit walk with --ancestry-path so upstream-only commits merged from the base branch are excluded, and added a merge regression. Fixed in 79eaa70.
| it("rejects disallowed files introduced after the existing PR head", async () => { | ||
| const { repoDir } = createRepoWithDisallowedHistoryFile(); | ||
| fs.writeFileSync(path.join(repoDir, "agent.js"), "console.log('agent');\n"); | ||
| execSync("git add agent.js", { cwd: repoDir, stdio: "pipe" }); | ||
| execSync("git commit -m 'agent script'", { cwd: repoDir, stdio: "pipe" }); |
There was a problem hiding this comment.
The regression now adds agent.js and removes it in a second commit before invoking the handler, proving per-commit detection survives a net-zero change. Fixed in 79eaa70.
Comment MemoryPeek at saved memory (pr-code-quality-reviewer)Note This comment is managed by comment memory.Expand the saved memory block to view or edit the persistent context for this thread.
|
There was a problem hiding this comment.
Blocking on one correctness bug and one coverage gap in the new incremental allowed_files check.
### Why I'm requesting changes
- The new fallback to
origin/<branch>is not a reliable stand-in for the current PR head, so this preflight can make the allowlist decision against the wrong commit range for fork PRs or same-name/stale tracking refs. - The added regressions only cover that fallback path; they never exercise the recorded PR-head baseline env vars that production uses for existing PRs, so the critical path remains unverified.
Please tighten the check to a recorded PR-head SHA/ref (or skip it when that baseline is unknown) and add a regression that proves the recorded-baseline path behaves correctly.
🔎 Code quality review by PR Code Quality Reviewer · copilot · gpt54 · 60.7 AIC · ⌖ 5.72 AIC · ⊞ 20K
Comment /review to run again
Comments that could not be inline-anchored
actions/setup/js/safe_outputs_handlers.cjs:1607
Falling back to refs/remotes/origin/(branch) here reintroduces the wrong-PR baseline bug for fork or same-name branches, so this preflight can block on author-owned commits or miss disallowed agent commits entirely.
<details><summary>💡 Why this blocks</summary>
When the recorded PR-head baseline is missing or rejected, origin/(branch) is not necessarily the current PR head. In fork PRs or wildcard/batch runs, it can point at another branch with the same name or at a stale tracking ref, which…
actions/setup/js/safe_outputs_handlers.test.cjs:2594
These regressions never populate the recorded PR-head baseline env vars, so they only exercise the origin/(branch) fallback and still miss the production path this patch is trying to fix.
<details><summary>💡 Why this matters</summary>
The behavioral change here is specifically about scoping to the existing PR head, but the new tests only seed refs/remotes/origin/feature/work and GITHUB_BASE_REF. They never set GH_AW_PR_HEAD_BASE_SHA/REF/PR_NUMBER, so they do not verify the recorded-baseline …
There was a problem hiding this comment.
Impeccable review (harden/audit focus — bug-fix change)
Scope: Scoped the allowed_files policy check for push_to_pull_request_branch from the full PR-branch history (origin/<base>..<branch>) to only the commits added after the existing PR head (prHeadBaseline or origin/<branch> fallback). Per-commit git log --name-only inspection is preserved so a disallowed file changed-then-reverted by the agent is still caught.
Findings:
- No security or correctness issues found. The narrowed range correctly uses the pinned SHA, falls back safely when no PR-head baseline is recorded, and remains non-fatal (falls through to apply-time enforcement) if git fails to resolve the base ref.
- Test coverage is solid: author-owned pre-existing disallowed files are no longer blocked, agent-introduced disallowed files are still rejected,
excluded_filesexemption still works, and bundle-transport pre-apply detection is covered for a PR with an existing head. - One minor non-blocking style note left inline: a duplicated fallback expression for computing the incremental base ref.
No blocking issues found.
🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · copilot · sonnet50 · 73.5 AIC · ⌖ 17.2 AIC · ⊞ 8.1K
| server.debug("Incremental allowed-files check skipped: branch SHA not pinned (non-bundle path)"); | ||
| } else { | ||
| const branchHistoryFiles = execGitSync(["log", "--name-only", "--pretty=format:", `origin/${baseBranch}..${pushPinnedSha}`, "--"], { cwd: pushGitCwd }) | ||
| const incrementalBase = prHeadBaseline?.sha || prHeadBaseline?.ref || `refs/remotes/origin/${entry.branch}`; |
There was a problem hiding this comment.
Minor: this fallback expression (prHeadBaseline?.sha || prHeadBaseline?.ref || refs/remotes/origin/${entry.branch}) is duplicated verbatim at line 1559 for the merge-detection check. Consider computing it once into a local (e.g. incrementalBaseRef) right after prHeadBaseline is resolved and reusing it at both call sites, so the two copies can't drift if the baseline-resolution semantics change later. Not blocking.
@copilot please address this.
There was a problem hiding this comment.
Computed incrementalBaseRef once after resolving the PR-head baseline and reused it for merge detection and allowed-file inspection. Fixed in 79eaa70.
There was a problem hiding this comment.
Skills-Based Review 🧠
Applied /tdd and /codebase-design to the allowed_files scoping fix. This is a well-targeted security correctness fix — moving from a full-branch history check to a per-commit check anchored on the existing PR head, with a documented non-fatal fallback. No blocking issues found; two minor suggestions below.
📋 Key Themes & Highlights
Key Themes
- Test coverage gap (
/tdd): several of the new/updated tests only assert on the error shape conditionally (if (result.isError) {...}), so they can silently pass without exercising the behavior they're meant to verify. Tightening these would make regressions in the allowed-files bypass path fail loudly instead of quietly. - Minor duplication (
/codebase-design): theprHeadBaseline?.sha || prHeadBaseline?.ref || refs/remotes/origin/${entry.branch}fallback expression is repeated identically in two places; a shared constant would prevent drift.
Positive Highlights
- ✅ Good security instinct: per-commit inspection (
git log --name-only) instead of only net diff, so a disallowed file changed-then-reverted by the agent is still caught. - ✅ Uses the already-pinned SHA (
pushPinnedSha) as the range head to avoid TOCTOU, consistent with the surrounding bundle-generation code. - ✅ New integration test (
checks only bundle commits added after an existing PR head) exercises the bundle-based path realistically with real git repos/bundles, not just mocks. - ✅ Non-fatal fallback preserved and well-commented when the PR head baseline isn't resolvable, so apply-time policy enforcement still backstops this check.
@copilot please address the review comments above.
🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · copilot · sonnet50 · 120.1 AIC · ⌖ 14.5 AIC · ⊞ 10.1K
Comment /matt to run again
Comments that could not be inline-anchored
actions/setup/js/safe_outputs_handlers.test.cjs:2606
[/tdd] Weak assertion: if (result.isError) { ... } only checks the error shape when an error happens, but never asserts that the call actually succeeds (or at least doesn't trip the allowed-files check). If a future regression makes pushToPullRequestBranchHandler always return a non-error result for an unrelated reason (e.g. git plumbing failure swallowed elsewhere), this test still passes without ever exercising the real assertion.
<details>
<summary>💡 Suggested fix</summary>
Asse…
actions/setup/js/safe_outputs_handlers.cjs:1559
[/codebase-design] prHeadBaseline?.sha || prHeadBaseline?.ref || \refs/remotes/origin/${entry.branch}`is duplicated verbatim at line 1607 for the allowed-files check. Both call sites need the exact same "effective incremental base" concept — extracting it into a small named helper/const once (e.g. right afterprHeadBaseline` is resolved) would prevent the two from drifting if one is edited later.
<details>
<summary>💡 Suggested fix</summary>
const effectiveIncrementalBase = …
</details>|
@copilot address the following outstanding work in one pass:
Push the necessary fixes, reply to each listed review thread and resolve it when addressed. Ignore feedback already answered or resolved. Use the pr-finisher skill and stop when only human review or CI remains; do not trigger CI. Sous-chef head: b3ebeca
|
…iles-policy Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
|
@copilot address the following outstanding work in one pass:
Push the necessary fixes, reply to each listed review thread and resolve it when addressed. Ignore feedback already answered or resolved. Use the pr-finisher skill and stop when only human review or CI remains; do not trigger CI. Sous-chef head: dcbda10
|
…iles-policy # Conflicts: # actions/setup/js/work_queue_compaction.test.cjs Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>

push_to_pull_request_branchcould reject an allowed agent change because its emit-timeallowed-filescheck scanned earlier, author-owned commits on the PR branch.