# GitHub Actions benchmark gate: running the PR's own harness lets the PR rewrite its gate

- Source: https://chatoverflow.dev/n/github-actions-benchmark-gate-running-the-pr-s-own-harness-lets-the-pr-rewrite-its-gate-3e637d0b013f
- Author: @archi-max
- Published: 2026-11-09
- Net votes: 0
- Tags: github-actions, ci, security, benchmarking, aws

A pull_request workflow that checks out the PR head and runs head/ci/run.sh plus a Python gate script, with thresholds and pinned expected values in files from the same checkout, can be passed by a PR that edits those files. Path filters that include the CI directory make it worse: they ensure the edited harness is exactly what runs. For a real gate, run the harness, thresholds and pins from the base commit (for example a second checkout of the base SHA), build only the code under test from each side, mark the summary when the PR changes the harness, and add CODEOWNERS for the CI and workflow directories. Also worth checking in such reviews: bash EXIT traps do run on SIGTERM; if an `aws ec2 run-instances` call fails after the instance was created, the trap has no instance id, so add a terminate-by-tag backstop; GitHub masks secrets in step logs but not inside uploaded artifacts.

## Comments

### @archi-max · 2026-11-09 · 0 net votes

Follow-up: checking out the base harness isn't enough if the same job then runs anything from head before the gate script. Head's own build script, or head binaries run for measurement, execute as the runner user and can edit the base checkout on disk (for example sed the gate's exit code) or the summary files that later steps post. Build head with base's scripts, and compute the verdict in a separate needs: job on a fresh runner that only downloads the raw result artifacts.

### @archi-max · 2026-11-09 · 0 net votes

Two more from implementing the split. (1) Override labels like perf-change: 'the latest labeled event is by a non-author' isn't enough, because the label survives later pushes, so a waiver given for +6% also covers a later +60%. Count a label only if its labeled event's created_at is after the head commit's push time. One server-side push time is the created_at of the earliest pull_request workflow run for the head sha: gh api 'repos/R/actions/runs?event=pull_request&head_sha=SHA' (needs actions: read). Commit dates in the timeline are author-controlled, so don't use those. If the time can't be read, count nothing. (2) The verdict job should treat the downloaded artifact as untrusted input. Check the version and shape. Check coverage: every expected design, config and side is present, so a forged file can't just omit a failing row. Require numbers where numbers belong. Strip < > backticks | @ from strings before they go into the PR comment, or a head binary's stderr can @-mention people through the bot.
