Skip to content

Prevent stale-base signed replay from synthesizing unrelated changes; enforce policy on GraphQL payload#36937

Draft
Copilot wants to merge 6 commits into
mainfrom
copilot/fix-signed-commit-push-issues
Draft

Prevent stale-base signed replay from synthesizing unrelated changes; enforce policy on GraphQL payload#36937
Copilot wants to merge 6 commits into
mainfrom
copilot/fix-signed-commit-push-issues

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Jun 4, 2026

When safe-outputs runs on a shallow/stale checkout and base advances, signed replay could compute fileChanges from an old parent while targeting current origin/<base>, producing large unrelated reverts and bypassing protected_files checks. This change hardens signed replay so payload synthesis is based on a compatible base and policy is enforced on what is actually sent to GraphQL.

  • Signed replay base-alignment (stale-parent guard)

    • Detects mismatch between replay parent and GraphQL parent.
    • If current GraphQL parent is not an ancestor of HEAD, rebases local replay range onto current parent before GraphQL replay.
    • On rebase conflict, aborts and fails with explicit guidance instead of emitting synthesized unrelated changes.
  • Payload-level policy enforcement (defense in depth)

    • Validates synthesized fileChanges (the actual GraphQL payload), not only agent-emitted patch text.
    • Enforces:
      • max_patch_files
      • max_patch_size
      • protected_files policy
    • Treats violations as hard refusal paths (no unsigned push fallback).
  • Bundle history readiness in shallow clones

    • ensureFullHistoryForBundle now unshallows (git fetch --unshallow origin) before bundle processing so prerequisite ancestry/merge-base logic is reliable.
  • Handler integration

    • create_pull_request and push_to_pull_request_branch now pass handler config into pushSignedCommits as validationConfig, enabling payload-level policy checks during signed replay.
await pushSignedCommits({
  githubClient,
  owner,
  repo,
  branch,
  baseRef: `origin/${baseBranch}`,
  cwd,
  signedCommits,
  validationConfig: config, // enforce protected_files/max_patch_* on synthesized GraphQL payload
});

Copilot AI and others added 2 commits June 4, 2026 15:44
Co-authored-by: dsyme <7204669+dsyme@users.noreply.github.com>
Co-authored-by: dsyme <7204669+dsyme@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix signed-commit push to handle shallow checkouts correctly Prevent stale-base signed replay from synthesizing unrelated changes; enforce policy on GraphQL payload Jun 4, 2026
Copilot finished work on behalf of dsyme June 4, 2026 15:54
Copilot AI requested a review from dsyme June 4, 2026 15:54
Copy link
Copy Markdown
Collaborator

@dsyme dsyme left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unshallow should not be used,

dsyme added 3 commits June 4, 2026 17:55
Single 'git fetch --unshallow origin' is disastrous on high-churn
monorepos. Instead iterate 'git fetch origin <base> --deepen=N' with
progressively larger N (50, 100, 200, 500, 1000, 2000, 4000) until
every bundle-declared prerequisite satisfies
'git merge-base --is-ancestor <prereq> origin/<base>'.

Falls back to --unshallow only if iterative deepen exhausts, or if
a legacy caller omits the deepen options.
The two tests that asserted 'git fetch --unshallow' was called on a
shallow checkout were written against the old single-unshallow path.
With iterative --deepen they need to: declare a bundle prerequisite
(via mocked 'git bundle verify'), report it as not-an-ancestor of
origin/<base>, and then assert the first --deepen=<N> step was issued.
Copy link
Copy Markdown

@g-jobayer g-jobayer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixes #35550

@github github deleted a comment from g-jobayer Jun 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Signed-commit push silently invents unrelated file changes (and bypasses protected_files) when checkout is shallow and base branch advances

3 participants