01 The pull request
A data agent learns to answer free-form questions
On main, analysis-agent answers questions about a CSV by
letting the model pick one named aggregation from an allowlist. Safe, boring,
capped. Then a PR lands: “support natural-language queries.” It asks the
model for a pandas expression and evaluates it against the dataframe. Every line looks
reasonable in review — and a prompt-injected cell in the CSV now reaches
eval().
op = resp.choices[0].message.content.strip() if op not in ALLOWED: # validate against an allowlist raise ValueError(op) return getattr(df, op)(numeric_only=True) expr = resp.choices[0].message.content return eval(expr, {"df": df}) # model output executed directly
02 The gate
One command, scoped to the diff
In the PR’s CI job — or locally before you push — one line. It compares the branch against its merge-base and rules on what this change introduced, never inherited debt.
03 The verdict
Clean on main → blocked on the PR
Same agent, two states. The baseline promotes. The change that added the
eval flips it to a block — and names the exact line and why.
main before the PR
100 / 100
Introduced by this change — not pre-existing
eval() executes expr — the model’s own output.
max_tokens; a single response can run to the model’s max output.
1.04 Why you can trust the red
A gate teams keep, not one they mute
- Net-new only. It blocks what this PR introduced and never fails you on debt you inherited — so the red always means “you just added this.”
- Confirmed, not guessed. The HIGH is graded
confirmed because the source is visible in scope: the value came from
client.chat.completions.create(…)and reacheseval()in the same function. When provenance can’t be proven, it says so and stays advisory — it doesn’t cry wolf. - It’s just an exit code.
0promote ·10hold ·1block. Drops into any CI without a dashboard, an account, or your code leaving the runner.
05 Run it yourself
The whole example is in the repo
Nothing here is staged. The two agent versions and a script that builds the git
scenario and runs the gate live under
examples/demo-code-risk/. Reproduce the output above in about thirty seconds:
Point it at your agent
Add the same gate to your PRs. It reads the code, rules on the change, and comments the verdict — free and open-source.
# .github/workflows — on every pull request
- uses: VamsiSudhakaran1/release-gate@v0.9
with:
command: pr
base: origin/main