Appearance
Run any coding model over a vulnerable snippet and it lights up. That part is easy. The harder part is the next step: after the fix lands, does the model calm down, or does it keep flagging the same code as vulnerable? For a security triage tool, that second behavior decides whether anyone keeps the tool on.
Three recent evaluation projects circle the same problem from different sides. The ART benchmark on Kaggle measures whether models respect security patches instead of just spotting dangerous tokens. UK AISI and EvalEval released shared infrastructure so published benchmark results can actually be reproduced. OpenAI introduced MentalHealthBench, an expert-informed benchmark for helpful and safe AI responses in realistic mental health conversations. Different domains, same reframe: score the model on behavior in context, and drop "did you find the scary word" as the success criterion.
What "found the bug" misses
Public coding evals ask one question: did you find a bug? They rarely ask the follow-up: did you respect the fix? The ART project started from that gap. Its dataset builds minimal-pair twins, two snippets that share the same function name, identifiers, and overall shape, with only the security control differing. Models receive the snippet and the language. No gold label, no rationale, no hint about which twin is patched.
Here is a real pair from the set. Everything a token matcher keys on, the raw SQL concat, the function name, the $_GET["id"] superglobal, is identical. The only difference is the fix:
php
// twin_sql_php - gold = reachable_vuln
function process_user_data($conn) {
$id = $_GET["id"];
$sql = "SELECT * FROM users WHERE id = " . $id; // attacker-controlled concat
return mysqli_query($conn, $sql);
}
// twin_sql_php - gold = patched (same shape, one control added)
function process_user_data($conn) {
$id = (int)$_GET["id"];
$stmt = mysqli_prepare($conn, "SELECT * FROM users WHERE id = ?");
mysqli_stmt_bind_param($stmt, "i", $id); // cast + prepared statement
mysqli_stmt_execute($stmt);
return mysqli_stmt_get_result($stmt);
}When a model labels that second snippet reachable_vuln, detection was never the failure. Patch reading was. ART quantifies exactly that with Twin Gap: vulnerability accuracy minus patched accuracy. Zero means the model respects fixes. A positive number means it over-flags code that has already been locked down.
How the dataset is built
The dataset is intentionally small: 8 twin pairs plus 6 safe and vacuous controls. One miss moves Twin Gap by 12.5 percentage points. That's deliberate. This is a diagnostic probe, not a large-N ranking claim, and the repo says so. The pairs cover SQLi, XSS, auth bypass, command injection, path traversal, LFI, and insecure deserialization across PHP and Python. The classes mirror recurring production patterns, WordPress-plugin-style PHP and Flask/Django-style request handling.
The synthetic choice matters. Raw CVE examples let a model win by memorizing a write-up. Synthetic twins force the model to either read control flow or pattern-match on "prepared statement present, therefore safe." The comments on the write-up rightly identify that second path as the next gap: fix tokens can be present while the vulnerability survives, and a probe that only includes correctly patched twins can't tell a careful reader from a token rule.
What seven models revealed
Seven locked models ran the main task: three Gemini tiers, two Claude tiers, open-weight Gemma, and GPT-5.4 Nano. They span roughly a 50x cost range, from about $0.004 to $0.18 per triage run. It's a tier-and-price lineup, not a single-model race.
| Model | ART | Raw | Patched | Controls | Twin Gap | Cost USD | Latency |
|---|---|---|---|---|---|---|---|
| gemini-2.5-pro | 1.000 | 1.000 | 1.000 | 1.000 | 0.000 | 0.181 | 7.9s |
| gemini-3.5-flash | 1.000 | 1.000 | 1.000 | 1.000 | 0.000 | 0.108 | 2.9s |
| gemini-3.7-flash | 1.000 | 1.000 | 1.000 | 1.000 | 0.000 | 0.028 | 9.1s |
| gemma-4-31b-it | 1.000 | 1.000 | 1.000 | 1.000 | 0.000 | 0.007 | 12.3s |
| claude-sonnet-4-5-20250929 | 0.950 | 1.000 | 0.875 | 1.000 | 0.125 | 0.060 | 3.1s |
| claude-haiku-4-5-20251001 | 0.850 | 1.000 | 0.625 | 1.000 | 0.375 | 0.020 | 1.7s |
| gpt-5.4-nano-2026-03-17 | 0.817 | 1.000 | 0.875 | 0.333 | 0.125 | 0.004 | 1.3s |
Every model caught every vulnerable twin. 100% raw detection across the board, and it separates nobody. The useful column is Twin Gap.
Four models, the three Gemini variants plus Gemma, scored perfect ART 1.000. Gemma did it at about $0.007 per run, roughly 4% of what the Pro-tier run cost. Heavy Pro didn't beat Flash on this probe. If you need open weights or on-prem deployment, Gemma is the standout at this exact task.
Haiku caught every bug too, then kept 3 of 8 patched twins flagged. That's Twin Gap 0.375, the worst patch reading in the group. Its 1.7 second latency is fast, but you'd spend that time back in the triage queue. Nano priced itself at $0.004 and then called 2 of 3 harmless controls risky. Cheapest run, but you pay in human review time.
Key numbers: All seven models hit 100% raw vuln detection. Twin Gap ranged from 0.000 on the top cluster to 0.375 on Haiku. Gemma reached ART 1.000 for about $0.007 a run. GPT-5.4 Nano flagged 2 of 3 harmless controls as risky.
The gold-adjudication story
Then the results got interesting for the wrong reason. All seven models disagreed with two gold labels, and they did it in the same direction. They turned out to be right. One filler item that looked like an escaped input was actually patched by the prompt's own definition. One deserialization twin that swapped pickle.loads for json.loads was genuinely safe. Until that adjudication, every model was capped at ART 0.917, which looked like a shared weakness. It was a broken key.
The lesson generalizes. Before trusting any single-shot score, validate the harness. Sonnet's proof-marker task sat at 0.0 through retries because the provider returned an empty completion. 86 prompt tokens in, nothing out. Read the transcript before ranking a model on that cell.
Personas and forced chain of thought did not fix patch respect. The red-team persona didn't inflate overclaim. Forcing Haiku to trace data flow moved its gap from 0.625 to 0.50, real progress but nowhere near closed. When reasoning doesn't close a gap, treat it as an attention problem rather than a hard capability ceiling.
Reading the comments on the ART write-up matched my own experience with triage pipelines. False positives kill security tooling faster than false negatives do. Nobody turns a scanner off for missing something once. They turn it off when it keeps re-flagging code the team already remediated, because in a regulated environment a reopened finding re-opens a closed audit item and creates a paper trail someone has to unwind. Several commenters pushed for a third test arm: patches that look right but are wrong, a prepared statement with an interpolated table name, an int cast on one sink while a second stays raw. If you only test correctly patched twins, a token matcher can pass. The decoy arm tells you which one you actually bought.
Reproducible results, not just headlines
A separate effort from UK AISI and EvalEval attacks the other side of the same problem: when someone reports a benchmark score, can anyone verify or compare it? Running frontier evaluations again is expensive, sometimes prohibitively so. Results get published across formats and platforms without setup details. The shared answer is the Every Eval Ever schema, plus an open platform called Evaluation Cards that binds benchmark metadata, run data, and model metadata into one interpretable record.
AISI released verified results, context, and configuration for five benchmarks from their paper on inference compute and frontier LLM evaluation: HealthBench, FrontierMath, Humanity's Last Exam, SWE-Bench Pro, and Terminal-Bench 2.0. The model coverage spans Claude Opus 4, 4.5, and 4.6 plus GPT-5, 5.2, and 5.4, with two related cyber evaluations on a partly different set.
The point isn't the list of names. It's the paired configuration. Scores on Humanity's Last Exam shift visibly with evaluation protocol and available inference compute. Without transcript-level detail, a reader can't tell what produced a number. With it, you can see cumulative token-budget curves, how many tasks a model solves as compute grows, and whether an oracle giving correctness feedback changes the trajectory. Open reporting turns a single score into an experiment you can actually examine.
MentalHealthBench and the same shift on safety
OpenAI's MentalHealthBench shows the same reframe outside security. It is an expert-informed benchmark for helpful and safe AI responses across realistic mental health conversations. The weight sits on "helpful and safe" as a pair. A model that deflects every sensitive topic is safe but useless. One that jumps straight to reassurance can be harmful in exactly the places it sounds most supportive. Scoring realistic conversations means evaluating that balance in context, not on isolated one-liners.
Quick Take: High detection accuracy is table stakes. The useful signal is whether a model stops flagging code after the fix, and whether the score comes with enough setup detail to mean anything.
Common pitfalls
- Treating 100% detection as the success bar. Every model in the ART probe caught every vulnerable twin. That column separated nobody. The models split on patched code, so benchmark patched-code accuracy alongside detection before shipping anything.
- Ranking models from single-shot cells. The proof-marker task scored 0.0 across retries because the provider returned an empty completion. Read the raw transcript, and validate the harness with known-behavior probes, before declaring a model failed.
- Trusting sanitizer presence over control flow. A cast, a prepared statement, or an escaping call in the text is not proof the sink is closed. Include decoy examples where fix tokens are present but the vulnerability is still reachable, or a token matcher will pass without reading the code.
- Comparing scores across evaluation setups. Humanity's Last Exam results shift with protocol and inference compute. Check the configuration, the evaluation card in EvalEval's terms, before treating two numbers as comparable.
- Assuming the gold label is ground truth. The seven ART models corrected two gold labels in unanimous agreement, and they happened to be right. When model consensus contradicts your key, audit the key first.
One thing to remember
The pattern across all three projects is simple to state and hard to practice: a score only means something when you know what was measured, how the run was configured, and what the benchmark designers assumed. ART makes patch respect visible. Evaluation Cards make run configuration visible. MentalHealthBench makes conversational context visible. Before you trust any number, ask whether that same visibility exists in your own evaluation.
The bottom line
- If you're building a security triage pipeline, rank models on patched-code accuracy alongside detection, because every model in this probe caught every bug and only patch respect separated the ones you can ship.
- If you're reporting evaluation results, publish setup configuration and transcript-level detail, ideally through the Every Eval Ever schema, so other teams can compare scores without re-running expensive frontier evals.
- If you're evaluating models for sensitive conversations, use expert-informed benchmarks that measure helpfulness and safety together in realistic contexts, because single-turn accuracy misses the harmful failures that appear mid-conversation.