feat(e2e): gate fork PR runs with pull_request_target - #2106
Conversation
Site previewPreview: https://170a1f81-site.fullsend-ai.workers.dev Commit: |
|
🤖 Finished Review · ✅ Success · Started 6:56 AM UTC · Completed 7:11 AM UTC |
ReviewFindingsMedium
Low
Info
Previous runReviewFindingsHigh
Medium
Low
Info
Previous run (2)ReviewFindingsMedium
Low
Info
Previous run (3)ReviewFindingsMedium
Low
Info
Previous run (4)ReviewFindingsMedium
Low
Info
Previous run (5)ReviewFindingsMedium
Low
Info
Previous run (6)ReviewFindingsMedium
Low
Info
Previous run (7)ReviewFindingsHigh
Low
Info
Previous run (8)ReviewFindingsHigh
Low
Info
Previous run (9)ReviewFindingsCritical
High
Medium
Low
Info
|
636d443 to
0343838
Compare
|
🤖 Finished Review · ✅ Success · Started 7:14 AM UTC · Completed 7:29 AM UTC |
|
🤖 Finished Review · ✅ Success · Started 8:18 AM UTC · Completed 8:32 AM UTC |
ralphbean
left a comment
There was a problem hiding this comment.
LGTM. Two minor notes inline.
Use pull_request_target so fork PRs can access e2e secrets, with a separate gate job that authorizes trusted authors or a fresh ok-to-test label before checking out PR head code. Post a sticky comment when blocked. Signed-off-by: Barak Korren <bkorren@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com>
Require authorized=true for all pull_request_target runs instead of treating a skipped gate as approval. Fix broken workflow link in docs. Signed-off-by: Barak Korren <bkorren@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com>
Add auth script test for empty timeline fallback path and cross-reference ADR 0009 from the e2e testing guide. Signed-off-by: Barak Korren <bkorren@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com>
Cover the timeline-empty fallback path when a fresh ok-to-test label is compared against committer dates from the commits API. Signed-off-by: Barak Korren <bkorren@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com>
Cancel in-progress runs for pull_request_target (github.ref is base branch on PR events). Drop commits API committer.date fallback; fail-closed when timeline has no push events. Signed-off-by: Barak Korren <bkorren@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com>
7ac778a to
a95ef5d
Compare
waynesun09
left a comment
There was a problem hiding this comment.
6-agent review squad — new findings (deduplicated against existing reviews)
Ran 6 parallel review agents (2x claude-coder, 2x claude-researcher, gemini-code-review, cursor-code-review). After deduplication against fullsend-ai-review bot (3 runs), @ralphbean's approval, and @ifireball's responses, 5 new findings remain that were not previously raised.
New findings
| Severity | Finding | File |
|---|---|---|
| high | Timeline committed event lacks created_at — stale-label check uses spoofable timestamps by default, not just as fallback |
check-e2e-authorization.sh:52 |
| high | Test mocks use incorrect API schema, masking the above | check-e2e-authorization-test.sh |
| medium | Gate checkout should pin explicit base ref for defense-in-depth | e2e.yml:65 |
| medium | Gate job missing timeout-minutes |
e2e.yml:58 |
| medium | Comment marker <!-- e2e-gate --> can be hijacked by PR participants |
action.yml:93 |
Already covered by existing reviews (not re-raised)
cancel-in-progressalways false — @ralphbean, non-blockingjq -s 'add'null guard — fullsend-ai-review, author accepted as fail-closed!cancelled()+ skipped gate — covered by critical bypass fix (0343838)- Commits fallback test gap — fixed in 7ac778a
Key takeaway
The most significant new finding is H1: the GitHub Timeline API's committed event has no top-level created_at field (verified against API docs). This means for regular pushes, the timeline path returns nothing useful, and the script always falls back to attacker-controllable committer.date. The test mocks mask this by using an incorrect schema.
Use committer.date for committed timeline events and created_at for head_ref_force_pushed. Explicit base ref on gate checkout, 5m timeout, and filter sticky comments to the workflow bot user. Signed-off-by: Barak Korren <bkorren@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com>
|
🤖 Finished Review · ✅ Success · Started 9:40 PM UTC · Completed 9:57 PM UTC |
|
🤖 Finished Retro · ✅ Success · Started 7:31 AM UTC · Completed 7:42 AM UTC |
Retro: PR #2106 — feat(e2e): gate fork PR runs with pull_request_targetTimeline: PR opened 2026-06-10 06:54 UTC by ifireball, merged 2026-06-11 07:28 UTC (~24.5 hours). 13 commits, 9 review bot runs, 3 CHANGES_REQUESTED verdicts from the bot, 2 human approvals (ralphbean, waynesun09). What went well:
What could improve:
Most improvement areas are well-covered by existing open issues. One new proposal filed for the API schema validation gap. Proposals filed
|
Keep enumerateVendoredPaths aligned with CollectVendoredAssets after main added the composite action (fullsend-ai#2106); fixes CI parity test. Signed-off-by: Barak Korren <bkorren@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com>
Closes #1604
Summary
Progress on #1604: enable fork PR e2e runs without the shim/
workflow_callindirection proposed in earlier designs. This PR uses a simplified single-workflow design (pull_request_target+ separate gate job) that provides the same security properties as the shim/gate pattern:ok-to-testafter latest pushGCP access via WIF is unchanged —
google-github-actions/authwithE2E_GCP_WIF_PROVIDER/E2E_GCP_SERVICE_ACCOUNTwas already implemented for e2e tests; this PR does not alter that path.ADR 0009 does not apply here. ADR 0009 documents
pull_request_targetfor shim workflows in enrolled repos that consume fullsend (static dispatch curl, no PR code checkout). This change is an internal CI workflow for fullsend itself, with a different threat model: it intentionally checks out fork PR code after authorization, documented in e2e-testing.md.Changes
pull_requesttopull_request_targetso fork PRs receive repository secretsgatejob that authorizes trusted authors (OWNER/MEMBER/COLLABORATOR) or a freshok-to-testlabel before the e2e job checks out PR head codeok-to-testlabels after new pushesProtected-path changes (
.github/workflows,.github/actions,scripts/) implement the authorization gate above.Test plan
bash scripts/check-e2e-authorization-test.shpasses locallyok-to-testafter latest push: e2e runs on head SHAok-to-test: label removed, e2e skipped until re-labeledok-to-testlabel event does not bypass gate (fixed in 0343838)ok-to-testlabel in repo settings if missing