Source-linked AI summary
Where AI Vulnerability Discovery Harnesses Go Quiet: Structural False Negatives and Hidden Vulnerabilities
Gadi Evron
TL;DR
Vulnerability-scanning harnesses can produce a clean-looking report even when a vulnerability was never analyzed or was dropped later. The paper catalogs structural drop mechanisms across harnesses and examines how those mechanisms affect reliability and evasion. Its conclusion is that harness rules can drop real, reachable vulnerabilities, while the supplied evidence does not measure how often these cases occur in real repositories.
Problem
A report with no findings does not distinguish clean code from a missed vulnerability or one that never reached the model or was removed afterward.
Source: §1 · p. 1Method
The paper catalogs drop mechanisms in harnesses and defines a drop as disclosed when a deliverable identifies the dropped item or provides a tied skip or prune count.
Source: §1 · p. 2, Rule 2, what counts as telling you · p. 5Results
The authors found that harness rules can drop real, reachable vulnerabilities, and that six drop classes appear in one harness while three appear in two.
Source: §10 · p. 29, §12 · p. 30Takeaways & Limitations
Builders should keep uncertain code in scope, report skipped code and failures as not analyzed, treat code text as data, and test with behavior-preserving changes.
Source: §12 · p. 30The authors did not measure how often the cases occur in real repositories, and several drop classes are observed in only one or two harnesses.
Source: §10 · p. 29
Abstract
from arXiv · showhide
LLM-based vulnerability discovery harnesses can miss real, reachable vulnerabilities because of how the harness around the model is built. Steps that select code, filter it, and store and merge findings can drop a vulnerability before or after the model runs, independently of the model's capability, and the report usually gives no sign that this happened. These drops come from engineering choices, and errors. They leave vulnerabilities undetected, and an attacker who knows the harness's rules can also use them to hide a vulnerability on purpose. Understanding these drops shows how to build harnesses that fix or disclose them and are harder to evade. Starting from the two harnesses we maintain, Knostic's OpenAnt and raptor, and then examining 10 additional open-source harnesses, we mapped 13 points where such drops occur and organized them into a taxonomy. Using each harness's own code, we show a single file that six harnesses dropped before their model saw its code, five of them without notice. We propose engineering failure patterns mapped to these drops, and relate them to Ptacek and Newsham's work on intrusion detection evasion. The paper also covers content-steered verdicts and prompt injection, and gives design principles and tests for harnesses that report accurately what they analyzed. The reliability findings likely apply to other LLM harnesses, beyond vulnerability research and application security, and the evasion findings apply wherever an attacker can write or influence the code being checked. We also argue that harnesses built to be descriptive can, in effect, be prescriptive. Rules written to describe typical code and typical model replies end up deciding what is analyzed, and anything that does not conform is treated as absent or as "no vulnerability."
1. Introduction
A report with no findings does not reveal whether the code was clean, the model missed a vulnerability, or a deterministic harness stage dropped it. The paper maps these structural drops across vulnerability-scanning harnesses and examines their reliability and evasion implications.
1. Introduction
- A no-findings report can look identical whether code is clean, the model misses a bug, or a harness stage drops it.Drops can happen before analysis, or after a finding is formed when a later stage rejects, suppresses, overwrites, or caches it.Source: §1 · p. 1
1.1 The harnesses we studied
- The study examines OpenAnt and raptor most closely, then considers other open-source harnesses with varied analysis architectures.The harnesses include tools that build their own call graphs, drive engines such as Semgrep or CodeQL, or use mostly-model plumbing.Source: §1 · p. 1, §1.1 · p. 2
1. Introduction
- Rules intended to describe typical code or model replies can become prescriptive when they determine what is analyzed and how replies are interpreted.Nonconforming code or replies may be treated as absent or as “no vulnerability.”Source: §1 · p. 2
- The authors catalogue 13 drop mechanisms across 12 harnesses, identifying when a real vulnerability can disappear from analysis or reporting.The examples are traced to source code or shipped instructions at specific commits.Source: §1 · p. 2
- The paper demonstrates ways to hide vulnerabilities from one or several harnesses and derives design principles and recommendations for more resilient harnesses.The proposed principles include keeping uncertain code in scope, reporting skipped code, and making harnesses harder to evade.Source: §1 · p. 2
1.1 The harnesses we studied
- The studied harnesses span tools that build their own call graphs, drive analysis engines, or rely mostly on models with thin plumbing.The authors maintain OpenAnt and raptor, which received the closest examination and supply many examples.Source: §1 · p. 1, §1.1 · p. 2
2. What a false negative is, and the kind we care about
The section defines structural false negatives as reachable vulnerabilities lost at deterministic harness stages, either before analysis or after a finding forms. It specifies when drops count as silent, how the harnesses were examined, and the attacker settings considered.
2. What a false negative is, and the kind we care about
- Structural drops occur when a deterministic stage prevents a reachable vulnerability from reaching analysis or removes a finding afterward.Examples include file-selection or parser limits before analysis and later rejection, suppression, overwriting, or stale cache results.Source: §2 · p. 4
- A vulnerability is reachable if a live entry point can hit it, regardless of what the harness’s call graph considers reachable.A drop is not silent when a report or named output records the excluded item or an attributable skip count.Source: §2 · p. 4
2.1 What counts as silent; Rule 1, where we look (the deliverable); Rule 2, what counts as telling you
- Silence is judged on consumer-facing deliverables, and disclosure requires a named dropped item or an attributable moved skip or prune count.A smaller total or stderr-only notice does not disclose the drop.Source: Rule 1, where we look (the deliverable) · p. 4, Rule 2, what counts as telling you · p. 5
Rule 2, what counts as telling you
- ccsr discloses its dropped Markdown finding in a named results file, while OpenAnt’s extension drop and Cisco’s named drops remain silent.OpenAnt’s test-path skip and VVAH’s excluded-directory count are disclosed through moved counts in outputs.Source: Rule 2, what counts as telling you · pp. 6–7
2.2 How we examined the harnesses
- The authors read each harness’s source at a pinned commit and isolated runtime-dependent stages on planted inputs, inspecting every deliverable.Model-dependent checks covered raptor’s corroboration gate in six runs and a planted-comment case in three trials.Source: §2.2 · p. 7
2.3 Threat model
- The threat model includes ordinary-code drops and hostile code authors who can choose scanned code, names, paths, comments, and contents but cannot change the harness.The attacker may also place a file outside a pull request’s diff and thus outside a diff-mode scan.Source: §2.3 · p. 7
3. The drop points we mapped
The paper maps thirteen deterministic pipeline drop points where real, reachable vulnerabilities can be omitted, often without notice. It also treats model-steered verdicts separately and identifies further cases left outside the taxonomy.
3. The drop points we mapped
- Thirteen deterministic pipeline drop points can keep real, reachable vulnerabilities from entering or leave them from the pipeline, often without notice.The taxonomy is not claimed to be exhaustive or to establish how common these mechanisms are.Source: §3 · p. 8
3.1 The thirteen
- File-selection and parsing rules can exclude files or code before analysis, while reachability errors can make vulnerable code appear dead.Examples include extension and keyword filtering, unparsed macros, missed framework entry points, and dropped call edges.Source: §3.1 · pp. 8, 10
- Stored-result handling can suppress a restored bug when an earlier fixed or false-positive status wins, removing it from counts, reports, and exports without warning.The taxonomy also identifies stale clean-result caches that persist after harness changes or repository changes.Source: §3.1 · pp. 9–10
- Scan limits can quietly omit remaining code, including lower-priority items, later pull-request files in fallback mode, or analysis stopped by per-item limits.The pull-request example fetches only the first 100 changed files and matters only in a fallback mode.Source: §3.1 · p. 9
- Verification filters can discard real findings when another engine fails to confirm them, a model rejects reachability, or a reply misses the required format.Three harnesses treat an unexpected or cut-off model reply as “no vulnerability.”Source: §3.1 · p. 9
- Suppression comments and inactive rules can hide issues without disclosure or leave vulnerabilities unsearched because the relevant analyzer never runs.The paper reports both suppressed findings without a suppression count and documented or shipped rules omitted from scans.Source: §3.1 · p. 9
3.2 Beyond the thirteen: the model as the drop point
- Content-steered verdicts and prompt injection are separate from the thirteen pipeline drops: scanned text can persuade a model to dismiss a real bug or redirect its agent.Some harnesses distrust safety claims or use untrusted-input handling and counter-escalation defenses.Source: §3.2 · pp. 11–12
3.3 What we did not map
- The authors leave additional candidate mechanisms unmapped because they did not trace them to a harness at a commit, including fixture limits and documentation trusted as deployed enforcement.They say each would require source evidence, a planted input, and checks of every deliverable.Source: §3.3 · pp. 12–13
4. Each drop point, in real harnesses
The authors ground their examples in mechanisms found in harness source code or shipped instructions, focusing most closely on OpenAnt and raptor because they know them best.
- Examples are tied to real mechanisms in source or shipped instructions, with file and commit citations where a single location exists.Source: §4 · p. 13
- OpenAnt and raptor receive the most attention because the authors maintain and know them best.Source: §4 · p. 13
- The authors also examined other harnesses, using them to establish how widely the problem appears.Source: §4 · p. 13
1 - Unrecognized File Types
Harnesses can exclude code through extension-based file selection before the model analyzes it. The examples range from full-repository scans to pull-request diff scans.
- OpenAnt selects a file’s language by extension, so extensionless or unlisted files are never parsed.The passage gives an extensionless executable and a .pyw file as examples; renaming the former to .py is the stated recovery.Source: §1 · p. 13
- Codex Security drops changed files with extensions outside its allowed list when building a pull-request scan’s file list.Source: §1 · p. 13
- ai-deep-sast, RepoAudit, ToB, and deepsec also use extension or file-pattern selection, leaving extensionless files uncollected.Their mechanisms include include-patterns, suffix lists, language globs, and matcher glob patterns.Source: §1 · p. 13
2 - Argument Count Mismatch
The examples show distinct ways reachability modeling and result handling can remove or deprioritize findings, while scan limits can omit code. These mechanisms vary across harnesses and can be conditional or disclosed.
2 - Argument Count Mismatch
- RepoAudit drops valid optional- or variable-argument calls from its data-flow links when argument and parameter counts differ.OpenAnt’s Swift parser instead keeps mismatched calls and counts unresolved ones, so that case is not silent.Source: §2 · p. 14
3 - Built-in Name Conflict
- OpenAnt can mistake a project PHP function named like a built-in for the built-in, making its command-injection path appear unused and leaving only totals reported.Its Python analysis partly avoids the issue for same-file definitions; the other harnesses read did not drop calls this way without disclosure.Source: §3 · p. 14
4 - Unrecognized Entry Points
- OpenAnt treats unrecognized Celery tasks, AWS Lambda handlers, and Django signal receivers as unreachable, while raptor only marks such handlers low priority.iris can omit framework-only handlers from model labeling when their untrusted input arrives as a handler parameter.Source: §4 · pp. 14–15
5 - Overridden Findings
- deepsec matches new findings to stored ones by vulnerability type and title, allowing an earlier fixed, false-positive, or accepted-risk status to suppress a restored bug.The finding is omitted from counts, pull-request comments, and exports, while the scan still exits successfully.Source: §5 · p. 15
6 - Scan Limit Cutoff
- OpenAnt’s priority-based scan limit drops items beyond the selected top items without notice; ccsr’s first-100-file limit matters only in fallback mode.In ccsr’s normal path, the separately fetched full diff means the code is still reviewed; the fallback omission is not a clean silent drop.Source: §6 · p. 15
7 - Verification Filtering
Harnesses can discard findings after analysis through corroboration gates, rigid reply parsing, inherited suppressions, inactive checks, stale results, and file skips. These rules can turn a real finding or unchecked code into an apparent clean result, sometimes without notice.
7 - Verification Filtering
- raptor drops model-only findings without corroboration, except when another engine or a domain-model invariant supports them; its pre-check covers only C, C++ and Python.A real reachable SQL injection can be omitted from the report, while a less certain “suspicious” finding would be reported.Source: §7 · p. 15
- ai-sast, iris, and RepoAudit treat replies outside their required formats as no finding, and RepoAudit also silently drops paths the model calls unreachable.Their respective checks require a “TRUE” prefix, parseable JSON, or a matchable “Answer:” line.Source: §7 · p. 16
8 - Suppression Comments
- raptor’s optional compiler scan honors in-code suppressions, while ai-deep-sast runs Semgrep without disabling # nosemgrep, so vulnerable lines may produce no finding.The raptor gap is limited to an opt-in scan in the studied version; Semgrep or CodeQL may still catch the bug.Source: §8 · p. 16
9 - Inactive Rules
- raptor’s eight documented custom CodeQL queries never run, and VVAH’s unsafe-deserialization specialist is absent from every shipped profile.Neither harness’s report indicates that these checks were not run.Source: §9 · pp. 16–17
10 - Stale Caching
- raptor’s non-expiring verdict cache omits harness version from its key, and VulnHunter resume skips repositories with existing results, allowing old clean results to persist.raptor’s cache can serve a months-old verdict when a harness update leaves the prompt unchanged.Source: §10 · p. 17
11 - Keyword-Based Skipping
- OpenAnt reports its test-file skip count, whereas ccsr silently drops diff files containing “@generated” and ai-sast’s path-keyword skips appear only in the console.VVAH also discloses its default tests/ exclusion in its report.Source: §11 · pp. 17–18
12 - Unparsed Code Blocks
Code that a harness cannot parse or capture can disappear before analysis, and diff selection can omit relevant files. A separate OpenAnt example shows that its call-graph rules can classify live code as unreachable.
12 - Unparsed Code Blocks
- OpenAnt’s Rust parser treats macro bodies as unreadable, while compile-based CodeQL capture misses code the build does not compile; ToB’s Semgrep skill also silently skips default-ignored paths.OpenAnt produced an analysis unit for a normal function but not the same sink inside fuzz_target!; iris has the same compile-only gap, including for uncompiled generated code.Source: §12 · p. 18
13 - Diff Blindspots
- In diff mode, deepsec selects added, modified, renamed, or copied files, omitting deleted files and unchanged files made unsafe by another change.OpenAnt also narrows diff scans to changed code, but marks and counts selected units.Source: §13 · p. 19
5. Proof of concept: hiding a vulnerability from one harness
- Renaming a live PHP sink function to a built-in name makes OpenAnt veto the call edge and prune the sink as unreachable, although runtime behavior is unchanged.The run leaves only an aggregate pruned-unit count, with no line naming the function; the figure contrasts the call graph before and after renaming.Source: §5 · p. 20, Figure 4 · p. 20
6. Proof of concept: hiding it from one harness three ways at once
A single live vulnerable file can encounter multiple independent selection rules, and stacked rules can conceal both the code and evidence that it was skipped. The examples extend this pattern across multiple harnesses.
6. Proof of concept: hiding it from one harness three ways at once
- Three independent OpenAnt gates—missing extension, placement under tests/, and exclusion from the pull-request diff—each drop the same live eval vulnerability.The application includes the extensionless tests/handler and exposes its vulnerable function through a live route.Source: §6 · p. 21
- Fixing any one of the three gates still leaves the file out of scope, and the earliest extension check prevents the other gates’ usual skip notices from being written.The test-path and diff drops each leave a notice when run alone; the stacked case suppresses those traces.Source: §6 · p. 21
7.1 One change, many harnesses (each through its own drop point)
- Stripping a vulnerable file’s extension caused six harnesses in the panel to drop it, while VVAH and ccsr resisted this particular change.The affected panel included OpenAnt, RepoAudit, ai-deep-sast, ToB’s Semgrep skill, Codex Security, and deepsec.Source: §7.1 · p. 22
7.2 One identical file, each harness tripped by its own selection rule
- On one identical live Python file, all six harnesses in the panel dropped the code before the model saw it; five drops were silent and VVAH disclosed its exclusion.Four harnesses tripped on the missing extension, VVAH on tests/, and ccsr on the @generated substring.Source: §7.2 · p. 23
- ccsr’s @generated check strips the file’s code from the diff before the model sees it, leaving only its filename; neither deliverable records that pre-model removal.Whether the model mentions the filename was not tested.Source: §7.2 · p. 23
8. Why harnesses miss vulnerabilities
The paper groups structural misses into failure patterns and proposes principles for preventing them. The patterns include mismatches between harness and runtime behavior, code-steered decisions, lost results, and interacting pipeline steps.
8.1 The harness reads code differently from how it runs
- The proposed principle is to read code as the runtime does and treat unclassified code as unresolved, not absent; name-, path-, and parser-based rules can otherwise exclude live code.The authors describe these descriptive rules becoming prescriptive because they determine what counts as code.Source: §8.1 · p. 24
8.2 The harness takes instructions from the code it checks
- Code text should be data, not instruction: deterministic markers can suppress analysis, and comments or fake verdicts can steer model decisions.One cited study found no significant overall effect from safety-claim comments but reported 28 induced misses; another reported 55–99% of correctly detected vulnerabilities turned benign by fake verdict text.Source: §8.2 · pp. 24–25
8.3 The harness loses results it already had
- The proposed result-handling principles separate “not analyzed” from “clean,” key stored results on all changeable inputs, and avoid treating errors or limits as passes.Examples include unparseable replies, scan caps, stale cache keys, inactive rules, and skips disclosed only in logs or aggregate counts.Source: §8.3 · pp. 25–26
8.4 How the steps combine
- Because a finding must pass every pipeline step, one dropping step can erase it; stacked drops can also prevent notices from other steps from appearing.The authors also identify uneven protection across languages and modes, and noise filters that create unreported areas.Source: §8.4 · p. 26
8.5 Summary
- The taxonomy’s summary maps the principles to drop classes: runtime-faithful analysis, code-as-data, accurate failure reporting, and result keys that reflect all relevant changes.The listed classes include unrecognized file types, entry points and code blocks; suppression and keyword skips; scan cutoffs, verification filtering, inactive rules, and stale caching.Source: §8.5 · p. 27
9. Building, testing and using harnesses
The paper recommends making harness coverage, uncertainty, failures, and skipped work visible, while testing deterministic stages and treating code written by others as adversarial input. Users should interpret clean reports cautiously and look beyond pull-request scans, logs, and cached verdicts.
9.1 Building harnesses
- Keep uncertain code in scope at lower priority, mark unresolved calls and entry points, and report skipped files, functions, and findings with reasons.Under a fixed budget, this still loses coverage, but makes the loss visible.Source: §9.1 · p. 27
- Record errors, timeouts, and unreadable replies as “not analyzed,” and key cached results to the harness version and other result-changing inputs.Reopen findings that reappear after being marked fixed.Source: §9.1 · p. 27
- Let findings stand without agreement from a second engine, use agreement to rank them, and override or record engine defaults that suppress code.Also test that every shipped rule and analyzer runs in a default configuration.Source: §9.1 · pp. 27–28
- Separate target text from instructions in prompts, never let a comment alone close a finding, and recognize that model upgrades cannot fix drops before or after model execution.OpenAnt’s static stages remove 96.4% of functions before a model runs, without a mechanism to keep uncertain code in scope.Source: §9.1 · p. 28
9.2 Harnesses that check code written by others
- When checking code written by others, treat code-selection inputs as untrusted; four of six harnesses dropped the same extensionless file at selection.The attacker can satisfy or avoid public harness rules through names, paths, comments, or code contents.Source: §9.2 · p. 28
9.3 Testing for missed findings
- Test for missed findings by making behavior-preserving changes to filenames, extensions, and other code features, then checking whether findings stay the same.These tests need no labeled dataset.Source: §9.3 · pp. 28–29
9.4 Using harnesses
- Read a clean report as “no finding was produced,” and look for skips beyond the main report, including console output and logs.In the demonstrations, five of six harnesses dropped a file before the model saw its code, without notice.Source: §9.4 · p. 29
- Run full scans as well as pull-request scans, clear caches after harness updates, and assume untrusted authors may choose names, folders, and comments to fit harness rules.Pull-request modes can omit deleted and unchanged files.Source: §9.4 · p. 29
10. Limitations
The harness sample was selected to illustrate mechanisms, not rank tools or estimate how often the cases occur. The demonstrations exercised file selection without models, and the study tested security harnesses only.
10. Limitations
- The 12 harnesses were selected for illustration, not as a ranking, and the study did not measure how often the cases occur in real repositories.Several drop classes rest on one harness, and three more on two; classes describe mechanisms, not prevalence.Source: §10 · p. 29
- The file-selection demonstrations exercised harness stages without their models, so they did not test whether models with file tools could recover dropped files.The limitation concerns recovery by models with file tools, not whether the selection stage dropped the file.Source: §10 · p. 29
- Design reasons are stated for OpenAnt, known to the authors for raptor, and inferred for the other harnesses.OpenAnt and raptor were examined most closely; other harnesses were examined to establish how widely the problem appears.Source: §10 · p. 29
- The study tested security harnesses only; its expectation that reliability findings extend beyond security is supported by reports elsewhere but was not tested here.The paper does not test whether its findings apply to other LLM harnesses or retrieval-augmented generation.Source: §10 · p. 29
11. Disclosure
The authors characterize the identified drops as engineering choices or ordinary bugs, not vulnerabilities for coordinated disclosure, and report notifying maintainers; several issues were fixed before finalization. Their conclusion maps 13 drop points across 12 open-source harnesses and shows how silent drops can leave vulnerabilities undetected or be used to hide them.
11. Disclosure
- The authors did not treat the drop points as vulnerabilities for coordinated disclosure: they are engineering choices or ordinary bugs in harness selection, parsing, verification, or reporting.They nevertheless informed every named harness’s maintainers before publication; several issues were fixed, including items in OpenAnt, raptor, and Rivian’s harness.Source: §11 · pp. 29–30
12. Conclusion
- Without an attacker, drops leave vulnerabilities undetected; an attacker who knows the harness rules can use the same drops to hide a vulnerability.Demonstrations also showed verdicts steered by comments or instructions planted in code.Source: §12 · p. 30
- One file was dropped before the model saw its code by six harnesses, five without notice; the paper maps 13 drop points across 12 open-source harnesses.The drops do not depend on the model, and reports usually give no sign of them.Source: §12 · p. 30
- Most drops occur in deterministic steps added to control cost and false positives, where rules describing typical code can prescribe what gets analyzed.Nonconforming code may be treated as absent, while other drops arise when a harness reports its own failures as clean results.Source: §12 · p. 30
- The paper recommends keeping uncertain code in scope, recording failures as “not analyzed,” reporting skips, treating code text as data, and testing behavior-preserving changes.Users should read a clean report as “no finding was produced.”Source: §12 · p. 30
- The reliability findings likely apply to other LLM harnesses, while the evasion findings apply wherever an attacker can write or influence the checked code.The paper calls for resilient harnesses that accurately report what they analyzed and are harder to evade.Source: §12 · p. 30