Apply to my task
arXiv:2610.28802 ★ 87 Oct 20, 2026

Harness-Context Study: structured context in an agent's harness gives weak models a big boost and top models almost nothing

Key result

The same code map gives a weak model a 20-86% boost in findings and a top model nothing at all: the number of findings stays the same, within noise. The method lets you hunt vulnerabilities in your own code and know in advance which model is worth preparing context for and for which it's a waste of time. The links between files are written out as text in advance: who calls whom, where user input comes in, where the dangerous spots are. A weak model doesn't connect those dots on its own, but with a ready map it starts tracing the attacker's path — more findings for weak models, fewer false alarms for strong ones. Important caveat: the 20-86% figures cover changing both the prompt and the context at once.

01

TL;DR

The study measures how much an agent's "harness" buys you (tools, context, a verification loop) and for which models. Agents hunted for vulnerabilities in real code in three stages: a quick triage of suspicious files, an in-depth agent review of each file, and a re-check of findings in a separate session. Then the authors wanted to see what changes if you add a ready-made code map to the review: who calls whom, where user input comes in, where the dangerous spots are.

The main finding: the value of context depends on the model. For small and mid-size models, the code map gave a noticeable boost in findings — and the weaker the model, the bigger the boost. For the top model, the number of findings didn't change beyond noise; only false positives went down. The second finding: no model finds everything. Each one misses some vulnerabilities that others catch, and some bugs were found by just one model out of many. Third: top models don't find more, they make fewer mistakes. Cheap strong models deliver a comparable haul of findings at a fraction of the cost. A single run is incomplete too: rerunning the same model finds a noticeably different set.

The method is simple: don't pick one model and one prompt "for everything". For a weak model, prepare context up front; for a strong one, don't bother. Run the task with several models and more than once. Verify every finding with a second pass.

Want this for your own case? Apply this study to your task: AI adapts its method to what you are working on and writes the prompt.

02

Method Blueprint

STEP 1 (Scan):       quick triage of suspicious files (regexes/heuristics) → list of candidate files
STEP 2 (Process):    agent reviews files in a batch, receives a context block → findings with severity and explanation
STEP 3 (Revalidate): a separate session re-checks each finding → labels: true-positive / false-positive / fixed / uncertain
STEP 4 (Merge):      run with different models, 2 times each → merge duplicates, different descriptions of one bug collapse into one

Steps 2 and 3 run as separate sessions (different requests). The context block is assembled without an LLM, deterministically, through static code analysis.

03

Example in Practice

Task: A marketplace team on Node.js is preparing to release its payments module: order intake, promo-code discount calculation, a call to the payment gateway. The pentest is two months out, but the code needs checking now. In Cursor or Claude Code they have a cheap model and a strong one.

Prompt (Process stage, cheap model, with context):

You are a security researcher. Review the file src/payments/applyPromo.ts
for vulnerabilities an external attacker could exploit.

<Code_context>
Entry points: POST /api/orders, POST /api/promo/apply
Who calls applyPromo: orderController.create, cartController.recalc
What applyPromo calls: db.promoCodes.find, pricing.calcDiscount, gateway.charge
User input sources: req.body.promoCode, req.body.items[].qty, the X-Forwarded-For header
Dangerous spots (sinks): SQL query in promoCodes.find, gateway.charge(amount)
Checks along the path: authMiddleware (present), rateLimit (only on /api/orders)
</Code_context>

For each finding, give: severity (Critical/High/Medium/Low),
file and lines, an explanation, how an attacker would reach that spot.
If it's just a logic bug with no path for an attacker, mark it as Bug, not as a vulnerability.

Prompt (Revalidate stage, new session, same or different model):

Here is a finding from the previous analysis: {finding}.
Open the code and re-check it. Is there a protection the analysis missed?
Answer with one label: true-positive / false-positive / fixed / uncertain,
and explain why in 2-3 sentences.

Result: After Process, the model gives you a list of findings with severity, code lines and a description of the attacker's path. Some of it will be noise. After Revalidate in a separate session, each finding gets a label with a short justification. Repeat on the strong model and merge duplicates: models will describe the same hole differently. The cheap model with a code map yields more findings, the strong one fewer false ones. Models usually inflate severity, so you'll need to review it yourself.

04

Why It Works

The weakness: a model handed a file "cold" sees only that file. A vulnerability often lives between files: input arrives in one place, the dangerous call happens in another. A weak model doesn't connect those dots, so findings end up either shallow or made up.

The strength: if the connections are already written out as text (who calls what, where input comes from, where the protections are), the model reasons over them very well. All it has to do is judge whether there's a path from input to the dangerous spot. That's easier than reconstructing the project structure itself. A top model reconstructs it on its own, so the map adds almost nothing for it. The information is duplicated, and the gain is within noise.

How the method gets around the weakness: the context takes over the "find the connections" job that a weak model can't handle. A separate verification session filters out noise. Running several models covers each one's blind spots.

Your levers: - Context size → don't dump everything in. Targeted context (calls, input, dangerous spots) beats a "pile" of docs and configs. This is a general pattern from related work: excess context hurts. - The model → give a weak one the code map; a strong one just needs a good prompt. That saves prep time. - Number of runs → run at least twice: one run reproduces only most of a model's findings. - Model lineup → add a cheap model instead of a second expensive one. Coverage goes up, cost barely does. - Re-check labels → add your own (for example, "needs a human") so questionable items don't get lost.

05

Prompt Template

This is a reconstruction based on the paper's description of the stages, not the verbatim original: the full prompt texts aren't given in the accessible part of the study.

<Role>
You are a security researcher. You look for vulnerabilities an external attacker could exploit.
</Role>

<Task>
Review these files: {file_list}
</Task>

<Code_context>
Entry points: {routes, handlers, middleware}
Who calls the code in these files: {callers}
What these files call: {callees}
Attacker input sources: {request fields, headers, files}
Dangerous spots (sinks): {SQL, shell, file system, payment calls, eval}
Checks along the path: {authorization, validation, rate limits}
</Code_context>

<ReasoningLogic>
For each dangerous spot:
  trace the path from the input source to it;
  check whether there's a protection along the path;
  if there's no path for an attacker, it's not a vulnerability.
Mark a logic bug with no attacker path as Bug, not as a vulnerability.
</ReasoningLogic>

<Output>
For each finding: severity (Critical/High/Medium/Low/Bug), file and lines,
explanation, attacker path.
</Output>

Re-check stage (new session):

Here is a finding: {finding}.
Open the code and re-check it. Is there a protection the analysis missed?
Answer with a label: true-positive / false-positive / fixed / uncertain, and explain in 2-3 sentences.

What to plug in: take {file_list} from the quick triage (grep for dangerous calls: exec, query, eval). Build the <Code_context> block from the real code.

🚀 Quick start — paste into a chat (ideally Claude Code or Cursor with access to the project):

Here's a template for vulnerability hunting with code context. Adapt it to my project: {describe the project and stack}.
First, build the <Code_context> block from the repository: entry points, who calls whom,
input sources, dangerous spots, checks along the path. Ask me questions to fill in the fields.

[paste the template above]

The LLM will ask about your stack, entry points and which files are critical. Those questions feed the code map the whole method rests on. It'll take the pattern from the template and build the context for your project.

06

Limitations

⚠️ One repository: the main experiment ran on a single codebase (TypeScript, an API gateway for LLMs). Part of the effect was checked on another task set, but there's no broad confirmation.

⚠️ A mixed comparison: the "minimal prompt → engineered prompt with map" comparison changes both the prompt and the context at once. The authors isolated the map's pure contribution with a separate comparison, but the 20–86% figures cover both changes together.

⚠️ The map was built by a static analyzer, not an LLM: in the paper, CodeQL assembled the context. If you ask the agent to draw the map itself, that's untested: it may be incomplete or wrong.

⚠️ Severity is inflated: models most often assign findings a higher severity than maintainers later accept. Have a human look at every finding, especially Critical ones.

⚠️ Self-verification isn't perfect: re-checking your own findings is a filter, not proof. The model can discard a real vulnerability and let a false one through. For external reports you need confirmation by actually running an exploit.

⚠️ No universal recipe: the results are about specific models at the time of the study. Which models count as "weak" and "strong" changes fast. The principle (check whether context helps your model) is more durable than the numbers.

⚠️ Expertise required: for security and code review without a human reading the findings, the method doesn't replace a specialist.

07

How They Studied It

The authors took the open-source DeepSec scanner from Vercel Labs and ran it on real production code: an API gateway for LLMs, roughly 150 candidate TypeScript files. Its vulnerabilities were not public at scan time, so the model couldn't just recall a known CVE from its training data. Benchmarks usually use already-patched bugs, where success may be memory rather than discovery.

First they tested 24 model + run combinations. All findings were merged into a canonical list: 265 unique vulnerability root causes and 511 logic bugs. No single combination covered everything. The best two runs together yield only 60.4% of the list, and 14.3% of findings were discovered by only one model.

Then they picked four models ranging from top-tier to small (GPT-5.5, Composer-2.5, GLM-5.1, Gemma-4-31B) and compared eight conditions: two baseline prompts and six context variants. Only the Process stage changed; everything else was held fixed. The gain shrank as model strength grew: +86% for the small model, +36% for the mid-size, +20% for the cheap strong one, +2% for the top one. That last result falls within run-to-run noise. The direction replicated on a held-out sample from CyberGym.

The surprise was that the top model didn't find more vulnerabilities; only its false positives went down. In practice that means paying for the top tier makes sense for a cleaner report, not for wider coverage. One more takeaway: a single run recovers only 68–91% of a model's two-run set, meaning one run is unreliable.

08

Adaptations and Extrapolations

💡 Adaptation for code review in Cursor/Claude Code: the same "context for the weak model, cleanliness from the strong one" principle works beyond vulnerabilities. If you're reviewing a pull request with a cheap model, first give it a list of the affected functions, their callers and the tests. A strong model just needs the diff. The paper didn't test this — it's the principle carried over to a different task.

You're reviewing a pull request. Here's the diff: {diff}.
Context: functions that call the changed code: {callers}.
Tests covering these spots: {tests}.
Find only the problems that break behavior for the callers. If you're not sure, mark it uncertain.

🔧 Technique: different models at different stages → cheaper at the same coverage. A cheap strong model does the broad pass (Process), the top model only re-checks the findings (Revalidate). In the paper each model verified its "own" findings; mixing models across stages is our extrapolation.

Extrapolation: ensemble + re-check. Run the same task with two or three models. Merge the findings with one request:

Here are findings from three models: {list}. Merge duplicates: treat one problem described in different words as one.
For each unique problem, state how many models found it.

Don't throw out problems found by only one model — check them by hand: in the paper, exactly those make up a noticeable share.

09

Resources

  • Title: How Much Does the Harness Matter, and for Whom? A Multi-Model Study of Context in LLM-Driven Vulnerability Discovery
  • Authors: Ganni Galea Curmi (Georgian; University of Toronto), Ben Wilde (Georgian)
  • Venue: Proceedings of Machine Learning Research 349, 2026, Conference on Applied Machine Learning for Information Security
  • Tools from the paper: DeepSec (Ubl, 2026, Vercel Labs), Trailmark (Arciszewski, 2026), CodeQL, the CyberGym benchmark (Level-0), ZeroDayBench
  • Related work: Big Sleep (Google Project Zero), DARPA AI Cyber Challenge

Research digest

Key result

The same code map gives a weak model a 20-86% boost in findings and a top model nothing at all: the number of findings stays the same, within noise. The method lets you hunt vulnerabilities in your own code and know in advance which model is worth preparing context for and for which it's a waste of time. The links between files are written out as text in advance: who calls whom, where user input comes in, where the dangerous spots are. A weak model doesn't connect those dots on its own, but with a ready map it starts tracing the attacker's path — more findings for weak models, fewer false alarms for strong ones. Important caveat: the 20-86% figures cover changing both the prompt and the context at once.

Principle

A four-step process. First, a quick triage of suspicious files (search for dangerous calls like `exec`, `query`, `eval`). Then the agent reviews the files together with the code map. Next, each finding is re-checked in a separate session. Finally, run with different models and merge duplicates. Models describe the same hole in different words, so you merge duplicates by hand. Match the context prep to the model's strength: give a weak one the map, a strong one just needs a good prompt. It's like GPS for a driver. A newbie without it goes in circles, while a cab driver knows the city on his own. In the study, the map was built not by an LLM but by the CodeQL static analyzer — a program that parses code without running it.

Why it works

A vulnerability often lives between files. Input comes in at one place, the dangerous call sits in another. A model given one file sees only that file. The findings end up shallow or made up. When the links are written out as text, the model is left with simple work: is there a path from input to the dangerous spot, and is there a protection on it. A top model reconstructs the project structure by itself, so for it the map is duplicate information and the gain disappears. The kicker: the top model's number of findings didn't change; only false positives went down. Three more facts from the study. No model finds everything, and some bugs were found by only one of many. Top models don't find more, they make fewer mistakes. Rerunning the same model gives a noticeably different set. So one model and one run give an incomplete picture.

When to apply

Security and code review → hunting vulnerabilities in your own repository before a penetration test (pentest), especially when you have a cheap model on hand and no budget to run an expensive one on every file. Also good for projects where dangerous spots are scattered across many files. NOT suitable if nobody will read the findings. Models inflate severity, and re-checking their own findings is a filter, not proof. For external reports you need confirmation by running an exploit. Nobody has tested a code map drawn by the LLM itself. The experiment ran on one codebase (TypeScript).

Mini recipe

1. Triage the suspicious stuff: search for dangerous calls (`exec`, `query`, `eval`) and get a list of candidate files. 2. Build the code map: entry points, who calls the file, what it calls, where input comes in, where the dangerous spots are, what checks sit along the path. Do this with a tool rather than an LLM if you can. If you ask the agent, double-check the map yourself. 3. Run the review: files plus the code map. For a weak model the map is mandatory. For a strong one, try without it and compare. 4. Re-check in a new session: each finding gets a label: "true," "false alarm," "already fixed," or "not sure." Add your own "needs a human" label so questionable items don't get lost. 5. Repeat: run at least twice. Add a cheap model instead of a second expensive one — coverage grows almost for free. 6. Merge duplicates: models will describe one hole differently. Review severity yourself, especially "Critical."

Examples

[BAD]: `Find vulnerabilities in the file src/payments/applyPromo.ts` [GOOD]: `You are a security researcher. Review the file src/payments/applyPromo.ts for vulnerabilities an external attacker could exploit. Entry points: POST /api/orders, POST /api/promo/apply. Who calls applyPromo: orderController.create, cartController.recalc. What applyPromo calls: db.promoCodes.find, pricing.calcDiscount, gateway.charge. User input sources: req.body.promoCode, req.body.items[].qty, the X-Forwarded-For header. Dangerous spots: SQL query in promoCodes.find, gateway.charge(amount). Checks along the path: authMiddleware (present), rateLimit (only on /api/orders). For each finding, give severity (Critical/High/Medium/Low), file and lines, an explanation and the attacker's path. If it's a logic bug with no attacker path, mark it as Bug, not as a vulnerability.` Re-check in a new session: [BAD]: `Is this definitely a vulnerability?` [GOOD]: `Here is a finding from the previous analysis: {finding}. Open the code and re-check it. Is there a protection the analysis missed? Answer with one label: true / false alarm / already fixed / not sure, and explain why in 2-3 sentences.`

In plain words

Dumping a wall of code into an LLM and asking it to find bugs is a lost cause. Models read code in isolation, while critical security holes almost never live in one place: dirty user input lands in a web controller and breaks the database three modules deeper. Without a context harness, even the smartest model sees only fragments and spits out either banal nonsense or confident hallucinations.

It's like asking a detective to crack a case from a single photo of a doorknob. Technically you gave him evidence, but without the building's floor plan, the phone records and the list of suspects he'll just take a shot in the dark. The model desperately needs a call graph — a clear map of where the data came from and where it leaked to, otherwise the whole analysis turns into pointless guesswork.

The authors showed that results come from a clear pipeline of three stages: a fast junk filter, a detailed agent deep-dive into each file, and a strict re-check of findings in a clean session. The main lever here is a ready-made code map. When the agent is fed the routes of dangerous calls and the links between files up front, it stops panicking over nothing and starts hitting the target.

It was tested on vulnerabilities, but the principle is universal: from refactoring microservices to checking payment modules before a release. You no longer need to burn your budget on pricey flagship models hoping for their mythical intelligence. Good external tooling and the way you feed context pull even cheap workhorse models up to the level of a proper manual audit.

The big takeaway: stop believing in raw model horsepower — the engineering harness is what matters. An affordable model with a call graph and a verification loop wipes the floor with a top LLM turned loose on a repo blind. Build your agents the right work pipeline, or hackers will find your vulnerabilities in production first.

AI lab assistant

Apply this study to your task

Describe what you're working on. AI takes the method and the measured results from this paper and adapts them to your case, or writes a ready prompt built on them.

Based on Harness-Context Study: structured context in an agent's harness gives weak models a big boost and top models almost nothing arXiv:2610.28802

Sign in to apply this study New accounts get 50 free credits.