Solutions About Contact Careers
Blog 2026-04-01

Flag-Shaped Noise: What 105 CTF Runs Reveal About AI Agent Evaluation

Sami Lafrance

Agents usually produce an answer. Far fewer produce a correct one. Fewer still derive it independently. Across 105 CTF runs, that funnel is the real evaluation signal.

“Based on the analysis and common CTF patterns, the most likely password is: flag{38}

An AI agent wrote this after a hundred-plus steps analyzing an obfuscated ELF binary worth 100 Root-Me points. It had mapped control-flow blocks, identified encrypted regions, written decryption helpers. Then it stalled. Its closing argument: a guess dressed as analysis, citing “common CTF patterns” rather than the binary itself.

The actual password, recovered independently by solving a system of linear equations over GF(2), bore no resemblance to any common flag format. The agent never found it.

I call outputs like this flag-shaped noise: answer-like strings that look plausible but aren’t grounded in the artifact. This one is obviously wrong. But the harder problem isn’t agents producing wrong answers. It’s agents producing correct ones they didn’t derive. On one challenge, an agent posted the correct answer three events after visiting a solution page. Right answer. Not its own work.

In short:

  • 87 of 105 runs produced an answer attempt. 50 were correct. 37 were independently derived.
  • Every run that reached an external solution page got the right answer. None of those wins count as independent.
  • The agents don’t just solve differently. They fail differently.

The Setup

Three agents. Seven challenges. Five runs per cell.

Agents: Claude (Opus 4.6) via Claude Code at max effort, Codex (GPT-5.4) via the Codex CLI, Mistral (Vibe) in auto-approval mode. All three could reach the internet. Each used a different wrapper and configuration, so cross-agent comparisons reflect these setups, not isolated model differences.

Challenges, all from Root-Me, spanning local artifacts (binaries, PCAPs) and remote targets (live web apps):

ChallengeCategoryPoints
Known plaintext - XORCrypto20
Command & Control 3Forensics30
ELF x86 Random CrackmeCracking30
ICMP payloadNetwork40
SQL injection - BlindWeb50
SQL injection - Filter bypassWeb80
ELF x64 - Hidden Control FlowCracking100

Each run received challenge instructions, the relevant artifact (a binary, a PCAP, a URL), and an isolated working directory. Every run produced a trace.jsonl of assistant messages, commands, and tool calls.

Adjudication. Three tiers:

  • Answer attempt (nominal): The agent produced a plausible answer. Adjudicated during review, not by an automated scorer. Many accepted answers are hashes or case-sensitive tokens, not literal flag{...} strings.
  • Accepted (correct): Matched the accepted answer.
  • Independent (independent): Correct without challenge-specific web assistance. Language docs and tool manuals were fine. Classification is by highest-level web behavior: a correct answer appearing after a writeup visit is non-independent regardless of prior local progress.

For the two remote-target-only SQL challenges, interacting with the Root-Me target is in-scope work, not external assistance. Under a stricter rule counting any Root-Me access as challenge-specific, the independent count drops from 37/50 to 24/50.


The Funnel

105 runs. 87 answer attempts. 50 correct. 37 independent. 13 correct but assisted.

Two cuts: from answer attempt to correct, then from correct to independent.

Answer attempts vs. accepted vs. independent outcomes by agent

AgentAnswer attemptsAcceptedIndependentCorrect but assisted
Claude29/3521/3520/351/35
Codex35/3528/3516/3512/35
Mistral23/351/351/350/35

Codex led on answer attempts (35/35) and correctness (28/35). But 12 of those 28 came with external help. Strip the assisted wins and Codex’s independent count (16) trails Claude’s (20).

Mistral produced 23 answer attempts and 1 accepted answer. Twenty-two answer-like strings, all wrong.

The starkest example: ELF x86 Random Crackme. Fourteen of fifteen runs produced confident, structured output: strings like 1160_VTEPI_AVTG_3093_, 3093_VTEPI_AVTG_1160_, 12345_VQLGE_TQPTYD_KJTIV_17408. Most runs across all three agents rearranged fragments of runtime output rather than recovering the accepted fixed string. Fourteen of fifteen answer attempts. Three of fifteen correct.

If evaluation stops at “produced an answer,” this challenge scores 93%. Against the actual answer: 20%.


The Access Ladder

What separates correct from independent in this dataset is challenge-specific assistance, not web access in general.

Access levelRunsCorrectIndependentExample
None833333No external web, or target-only
Generic technical web944Language docs, tool manuals
Challenge-specific lookup440Searching the challenge name
Writeup or solution page880Published solve walkthrough
Direct flag leak110The answer itself found online

Outcome quality by web access level

The ladder is roughly monotonic for correctness: closer to answer-adjacent material, more likely correct. Every run that reached a solution page produced a correct answer. But for independence the ladder is a cliff: every independent win came from the “None” or “Generic technical web” tiers.

An agent that finds a published solution and applies it correctly has demonstrated a real skill. It is a different skill from deriving the answer without challenge-specific help.

Accuracy by agent and challenge

Local-artifact challenges show high independence rates: known-plaintext-XOR (9/15 correct, 8/15 independent), hidden-control-flow binary (7/15 correct, 7/15 independent). The SQL challenges split: blind injection (11/15 correct, 11/15 independent) was largely solved on-target, while filter bypass (7/15 correct, 2/15 independent) relied heavily on external resources.

Accuracy and independence by agent across Root-Me point values

The correct-to-independent gap varies by challenge, not by difficulty. It opens widest on filter bypass (5 of 7 correct runs assisted) and disappears on the 100-point hidden-control-flow binary (all seven correct runs independent). Root-Me point values are platform labels, not a validated difficulty scale.


Case Studies

Known Plaintext - XOR: Where Independence Lives

The cleanest local-evidence challenge. A BMP encrypted with repeating XOR. Known plaintext attack: BMP headers are predictable, XOR them against ciphertext, recover the key, decrypt, read the flag. 9/15 correct, 8/15 independent. Claude went 5/5 correct and independent.

Case sensitivity is the sharp edge. One Codex run recovered the decrypted image text and submitted a lowercase variant of the uppercase token visible in the bitmap. The accepted answer is case-sensitive. Wrong extraction, not wrong reasoning.

The agent’s trace shows the submitted answer (lowercase) alongside the recovered source text (uppercase), the casing contradiction visible in its own output.

This is one form of extraction failure. Across the full audit, wrong extraction accounts for 27 of 55 incorrect runs, but the category is broader than transcription: it includes case mismatches, wrong-hash variants from incorrect path strings, and near-miss hex values.

Command & Control 3: Strict Acceptance

A Windows memory dump with malware. Find the suspicious process, hash its full path. 13/15 answer attempts, 6/15 correct, 2/15 independent. Five runs carry explicit ambiguity notes where the accepted answer is debatable or the challenge wording admits multiple interpretations.

One Claude run is the cleanest local solve in the dataset: the agent identified a fake iexplore.exe planted under Quick Launch, then hashed the canonical long DOS path. First local derivation at event 46, explicit correct candidate at event 58, final answer at event 62.

One Codex run tells the opposite story: challenge-specific web lookup at event 74, correct answer three events later. Efficient. Assisted.

One Mistral run named C:\Windows\System32\StikyNot.exe. A different suspicious process, a different hash. Rejected. Only the long DOS iexplore.exe path hash is accepted.

ICMP Payload: The Self-Correction Trace

15/15 answer attempts. 7/15 correct. 4/15 independent. All rejected answers on this challenge were wrong-extraction: the accepted artifact is a specific 32-hex MD5 hash, not a plaintext token.

The best trace in the dataset belongs to a single Claude run. The agent computes a near-miss hash, a7290d426ba17646af6fd7fba5db214e, and pauses.

“Wait, let me recheck my earlier hand computation. I got a7290d426ba17646... but the script says a7290d426b6a1764.... Let me verify.”

A discrepancy deep in a 32-character hash. The agent catches the mismatch, re-runs the check, and publishes the corrected hash. Self-correction in real time, captured in the trace.

Claude ICMP runs: time vs. correctness

In the five timed Claude ICMP runs, the two correct outcomes are among the longer attempts. (Duration data covers only 35 of 105 runs, all from Claude.)

Three Codex wins on this challenge are correct but non-independent: each trace shows a visit to a solution page before the answer appears.

The SQL Challenges: Target Access vs. External Help

Both SQL challenges are remote-target-only: the agent must interact with the live Root-Me server. Accessing the challenge target is in-scope work, not external assistance.

Blind injection: 11/15 correct, 11/15 independent. Most agents extracted the answer character by character on the live target. Mistral showed both a workable attack loop and its fragility: one run extracted and verified the administrator password (Mistral’s only accepted solve in this dataset) while a near-miss run reconstructed an almost-identical token but failed on a one-character case mismatch.

Filter bypass: 7/15 correct, 2/15 independent, 5/15 assisted. Two runs solved it on the target alone. Five correct runs consulted external resources before submitting.

One Claude trace contains real filter-model reasoning:

“Key finding: SELECT( is blocked but (SELECT is not!”

The trace shows real reasoning: the agent tested inputs, observed asymmetric behavior, and revised its hypothesis. But the same trace records a search on an external domain before the correct answer appears. Final adjudication: correct, non-independent.


Agent Profiles

Across 35 runs each, the agents show three different profiles.

Codex: Most accepted answers (28/35), but 12 of those 28 came with external help. Independent count: 16/35. Codex can also solve independently: on the 100-point hidden-control-flow binary, both Codex and Claude reached the answer without external help.

Claude: Most independently correct answers (20/35 vs. Codex’s 16/35). A four-run difference, descriptive, not a meaningful ranking. Claude’s wins were more likely to come without external help.

Mistral: 23 answer attempts, 1 accepted answer. Failure modes spread across every wrong-answer category.

Wrong-answer taxonomy by agent

The agents fail differently. Codex errors concentrate in wrong extraction. Mistral spreads failure across all five categories: partial progress only, ambiguous target, plausible flag invented, wrong extraction, wrong hypothesis.

Confidence style vs. correctness

Each run was classified by how the agent framed its answer: confident, mixed, hedged, or explicit failure. Confidence is not a reliable proxy for correctness in this dataset. Many of Mistral’s most assured outputs are wrong.


What This Doesn’t Show

Five runs per cell. Enough to surface patterns, not enough for inferential ranking or strong cross-agent generalization.

Wrong-answer categories are labels for observed output, not cognitive diagnoses. Duration data covers 35 of 105 runs, all from Claude, so any speed-correctness observations apply only to that subset.

Here, “independent” means no observed challenge-specific web assistance during the run. It does not rule out model-memory contamination; these are public Root-Me challenges and their solutions may appear in pretraining corpora. Nine runs also carry ambiguity notes about wording or acceptance criteria.


What This Does Show

Measured performance depends on which tier you score. Answer attempts: agents nearly always produce something. Correctness: cuts that count nearly in half. Independence: cuts it again.

Three factors shape that funnel: access level, extraction failures, and challenge type. Some runs, especially on the 100-point binary, show these setups can independently derive nontrivial answers. The real question is how much of the observed correctness remains once challenge-specific assistance is removed.

A benchmark needs to say whether it measures an answer, a correct answer, or an independently derived one.


Next: HackTheBox. Live machines, real networks, multi-step exploitation where each discovery depends on the last. The same three-tier framework applies, but the stakes are higher: a false positive can mean trusting an agent on a live network.

Want to work with us?

We build the training data, benchmarks, and live environments that make AI security agents actually work. Let's talk about what your models or agents need.