Pairing local models with sanitizers to audit 68 open-source repositories
- Published
- Data
- 68 audited open-source repositories (28 automated C/C++ campaigns and 40 deep repository audits), 338 static hazard slices, 245 semantic clusters, 89 escalated clusters, 32 tested static claims, 85 E1 execution proofs, 11 cleared codebases
- Figures
- 3
The claim
How do you use language models for vulnerability discovery without flooding engineers and open-source maintainers with false positives?
Standalone language models produce false-positive rates above 50% to 80% on static security review (Ullah et al., 2024; Li et al., 2025). When a model inspects a single function slice, caller bounds checks, compiler flags, and sentinel conventions sit outside its context window (Guo et al., 2025). Submitting unverified static model output to open-source maintainers or internal product teams wastes engineering time and erodes trust (Amusuo et al., 2025).
We solved this problem by pairing our co-resident local GPU stack (report 13) with a mandatory execution gate (E1). Before a reasoning model inspects any code, semantic deduplication (cosine >= 0.85) and a local 4B triage gate (report 07) filter candidate hazard slices. A local 38B code tracer then audits surviving clusters across caller chains and proposes a concrete trigger input.
No static finding enters our disclosure or remediation queue on model reasoning alone. Every candidate must reproduce under AddressSanitizer (Serebryany et al., 2012), UndefinedBehaviorSanitizer, go test, or a local loopback container socket harness. Both stages combine under a conjunctive law.
$$\text{Disclosable}(x) = \text{StaticTrace}(x) \land \text{HarnessRepro}(x).$$
Across 68 repositories (28 C/C++ campaigns and 40 deep audits), this gate held.
- 81.3% of high-confidence static model claims were false positives. In our 28 automated C/C++ campaigns, the slicer extracted 338 static hazard slices and deduplicated them into 245 clusters (
-27.5%). The local 4B gate (tau = 0.28) escalated 89 clusters (36.3%) to the 38B tracer, which produced 32 high-confidence static vulnerability claims. Compiled execution harnesses refuted 26 of those 32 claims (81.3%, or81.25%exact), leaving 6 confirmed C/C++ vulnerabilities (18.8%, or18.75%exact). - Only reproducible
E1proofs entered coordinated disclosure. Across all 68 repositories (28C/C++ campaigns plus40multi-language deep audits), our harnesses verified 85E1execution proofs across 32 projects. Another 137 code-level source traces (E2) without live execution proofs were held back from standalone disclosure. Across those 32 projects, we prepared 31 private coordinated vulnerability disclosure (CVD) packages (with 1 low-severity test-only finding excluded from advisory filing). All 31 packages are held under a 90-day embargo (ISO/IEC 29147). - 11 heavily deployed open-source codebases (
10applications and frameworks pluspyyaml's LibYAML C core) passed with 0 disclosable vulnerabilities. Local adversarial probe batteries clearedvercel/next.js,axios/axios,twisted/twisted,authelia/authelia,envoy,mlflow,fastmcp,mcp-python-sdk,xerj-org/xerj, andgithub/github-mcp-server. These runs included 201,904 fuzz inputs onenvoy, 535 route checks onmlflow, and 120 concurrent two-tenant races ongithub/github-mcp-server. In addition, 3,250,000 (3.25million)AddressSanitizerruns onpyyaml's LibYAML C loader produced 0 memory-corruption errors. - Enterprise pre-merge supply-chain checks. Engineering teams can run this sanitizer-gated workflow as a pre-merge control on vendored C dependencies, verifying
NUL-termination guards and CMake build pins before release.
The 68-repository open-source auditing pipeline and local-LLM triage stack in this study are independent research built with Carlos Juzarte Rolo. Carlos is a longtime friend, fellow Instituto Superior Técnico alumnus, and local-LLM hardware and systems specialist.
Four engineering rules for model-assisted security auditing
- Grade every finding by execution evidence (
E1,E2,E3) and gate disclosure onE1. ClassE3covers unverified static slices. ClassE2covers source-traced defects verified at repositoryHEADwithout a live exploit. ClassE1requires a reproducible sanitizer crash, unit test failure, or socket proof. OnlyE1findings trigger external advisories. - Deduplicate and triage locally before invoking deep reasoning. Embed normalized hazard slices in 76.8 ms (
1,024dimensions) and collapse near-duplicates at cosine0.85(Abbas et al., 2023). Score each cluster exemplar on a local 4B single-pass classifier in 212 to 226 ms (0output tokens) before waking the 38B model. - Test release-build macro semantics alongside debug assertions (
debugvsreleasebuilds). Many C and C++ codebases rely onassertorDCHECKmacros that vanish under-DNDEBUGin release builds. Conversely, other projects define custom macros that remain active in release binaries. Compiling both configurations underAddressSanitizereliminates macro guessing. - Verify harness portability to separate virtual-machine traps from memory bugs. Compiling C/C++ targets with
-march=nativeinside a container hypervisor can trigger CPUSIGILLinstruction traps. EveryE1crash must reproduce under a portable-O1 -fsanitize=address,undefinedbuild before being recorded as a memory defect.
The three-stage local triage and sanitizer verification pipeline
Running multi-repository security sweeps over metered cloud APIs is expensive because deterministic gates reject over 80% of candidates (report 13). Winning DARPA AIxCC systems treated models as hypothesis generators gated by sanitizers (Kim et al., 2025; Zhang et al., 2026).
We run three co-resident models across 4 local GPUs (128 GB VRAM). Those models feed containerized sanitizer build runners (Li et al., 2025; Nie et al., 2025).
| pipeline stage | component & model | latency / throughput | input volume | output volume | verification criterion |
|---|---|---|---|---|---|
| 1. Static hazard slicer | AST & regex hazard extractor (C/C++) |
< 1 s per repo |
28 C/C++ repos |
338 slices |
Flags DCHECK release hazards, error unwinds, and allocation math |
| 2. Semantic deduplication | Local embedding model (1,024-d) |
76.8 ms / slice |
338 slices |
245 clusters (-27.5%) |
Cosine similarity >= 0.85 collapses repeated bug shapes |
| 3. Single-pass 4B triage gate | Local 4B model (report 07, 0 output tokens) |
212 to 226 ms / cluster |
245 clusters |
89 clusters (36.3%, tau = 0.28) |
Symmetrized 2-option choice probability and CWE severity score |
| 4. Deep 38B code tracer | Local 38B model (2 concurrent workers) |
1,305 to 3,184 tok/s prefill |
89 escalated clusters |
32 static CONFIRMED claims |
Cross-caller source trace, trigger hypothesis, and minimal diff |
5. E1 execution oracle |
ASan, UBSan, go test, local sockets |
Seconds to 3.5 h fuzz |
32 static C/C++ claims |
26 refuted (81.3%), 6 confirmed (18.8%) |
Portable -O1 binary reproduction across 68 total repositories |

Across the 28 automated C/C++ campaigns, SemDeDup collapsed 338 raw hazard slices into 245 distinct clusters, removing 93 redundant slices (27.5%). Next, 89 of the 245 clusters (36.3%) cleared the local 4B triage gate (tau = 0.28) to enter the 38B code tracer. The 38B tracer then escalated 32 high-confidence CONFIRMED static vulnerability claims.
When we compiled those 32 targets with AddressSanitizer (Serebryany et al., 2012) and UndefinedBehaviorSanitizer, 26 of the 32 triggers (81.3%) failed to reproduce. Only 6 claims (18.8%) survived as genuine C/C++ vulnerabilities. We applied the same E1 execution rule across all 68 repositories (28 automated C/C++ campaigns and 40 deep audits). That full program produced 85 E1 executed proofs across 32 projects and 31 embargoed CVD patch packages.
Why 81.3% of high-confidence static claims failed execution testing
Inspecting the 26 refuted static claims shows why static language-model auditing produces high false-positive rates (Ullah et al., 2024; Zhang et al., 2024). In every refuted case, the 38B model flagged a plausible local hazard inside the target function. However, it missed an invariant enforced elsewhere in the repository or build system.
| refutation root cause | refuted claims (n=26) |
share of refutations | named open-source examples | what the static model missed | how the E1 gate refuted the claim |
|---|---|---|---|---|---|
| Upstream caller bounds clamping | 14 |
53.8% |
pgvector (4), libarchive (3) |
Callers clamp dimensions or window sizes before invoking the sink | Callee trace and ASan harness proved maximum allocation stays in bounds |
| Release macro & routing semantics | 6 |
23.1% |
clickhouse (4) |
Fuzzer inputs route to safe readers; custom asserts stay active in release | 230 curated seeds and release-flag inspection produced 0 target crashes |
| Non-NULL sentinel & ref conventions | 4 |
15.4% |
haproxy (1, 0.92 conf) |
Configuration parser terminates args[] with "" strings instead of NULL |
Native binary at HEAD validated group g1 users with rc = 0 and 0 crashes |
| VM CPU instruction traps | 2 |
7.7% |
Container hypervisor runs (2) |
-march=native emitted host SIMD instructions unsupported by the VM CPU |
Recompiling with portable -O1 eliminated the SIGILL traps (0 memory errors) |

Four named examples from the 26 refutations illustrate these failure modes.
- Upstream dimension clamping in
pgvector(4claims refuted). The static tracer flaggedcallocandpallocinteger-overflow hazards insparsevecandvector_inat high confidence. Tracing the upstream entry points and runningAddressSanitizershowed thatsparsevec_dim()already clamps dimensions toSPARSEVEC_MAX_DIM = 16383. That bound limitsmax_blocksto 128 KiB and checkswritten + nvalues > ndimsbefore allocation, making 32-bit multiplication wrap impossible. - Window and table clamping in
libarchive(3claims refuted). Inlibarchive's RAR5 reader, the reasoning model claimed a critical out-of-bounds heap write onwindow_sizeand anINT_MINtable allocation overflow inmake_table(). A callee-by-callee trace and 2,044-run sanitizer sweep proved that every caller capsR < 256KiB (bytes_to_read <= 768KiB inside a1MiBwindow_buf_size). Similarly,bits_read_int(16)and the existingtablesize <= 9guard clamptablesizeinto[10, 5040]. - Empty-string array sentinels in
haproxy(1claim refuted at0.92confidence). Onhaproxy, the 38B model reported aCWE-476NULLpointer dereference (0.92confidence) incfg_parse_users_groupwhenstrdup(args[cur_arg + 1])runs withusersas the final configuration token. Compilinghaproxynatively and passinggroup g1 usersreturned exit code0with 0 crashes. Throughouthaproxy, configuration argument arrays terminate with empty-string sentinels ("") rather thanNULL, sostrdupsafely copies an empty string. - Input routing and macro semantics in
clickhouse(4claims refuted). Inclickhouse, static claims predicted an out-of-bounds write inMergeTreeRewriteSourceand release-build assertion crashes. Running 230 curated reproducer seeds under a sanitizer build produced 0 crashes becauseFixedStringinputs route toFixedStringReadBinaryDataSourcerather than the hypothesized sink. - Virtual machine
-march=nativeSIGILLtraps (2claims refuted). In 2 early containerized fuzzing runs, our harness reported crash exit codes that looked like memory corruption. Inspecting the signal frames revealedSIGILL(illegal instruction) caused by-march=nativeemitting host CPU instructions that the virtual machine hypervisor masked out. Enforcing portable-O1compilation eliminated both false confirmations.
Eleven heavily deployed codebases cleared by adversarial probe batteries
A reliable security auditing pipeline should also measure and publish negative results. When an open-source project hardens its trust boundaries, verifying that adversarial probes fail closed gives engineering leaders concrete supply-chain assurance.
Across our 68-repository program, 11 heavily deployed open-source codebases (10 applications and frameworks plus pyyaml LibYAML C core) passed local E1 batteries with 0 disclosable vulnerabilities. In particular, pyyaml's underlying LibYAML C parser passed 3,250,000 (3.25 million) AddressSanitizer and UndefinedBehaviorSanitizer executions with 0 memory-safety crashes.
| open-source project | primary language & surface | adversarial probe battery executed | disclosable vulnerabilities | key defensive engineering control verified at HEAD |
|---|---|---|---|---|
pyyaml (LibYAML C core) |
C parser extension |
3,250,000 ASan & UBSan fuzz runs |
0 memory-safety bugs |
Clean C buffer management across 3.25 million parser executions |
envoy |
C++ L7 proxy (17 files) |
201,904 corpus fuzz inputs (3.5 h) |
0 |
Bounds-checked frame slicing and 0 sanitizer crashes across 201,904 inputs |
mlflow |
Python AI platform |
535 routes (388 Flask + 147 FastAPI) & 14 traversal probes |
0 |
MLFLOW_BASIC_AUTH_FAIL_CLOSED default-on and connect-time peer-IP SSRF pinning |
github/github-mcp-server |
Go MCP server |
120 concurrent 2-tenant tools/call races (6 batteries) |
0 |
Stateless: true HTTP mode, per-request context tokens, and off-host token stripping |
vercel/next.js |
TypeScript web framework |
15 attack-surface probe suites (max low CVSS 2.2) |
0 |
Symbol-keyed request metadata, DNS-pinned image SSRF guard, and host-free cache keys |
xerj-org/xerj |
Rust document parser |
14 crafted PDF & decompression-bomb probes |
0 |
Per-document subprocess isolation (1,536 MiB RLIMIT_AS, 120 s timeout, depth caps) |
authelia/authelia |
Go identity & OIDC portal |
14 authz & OIDC consent-rebinding probes |
0 |
Session-bound consent.Subject re-verification on every /authorize step |
axios/axios |
JavaScript HTTP client |
13 cross-origin redirect & 40 MB bomb probes |
0 |
Strict-origin header stripping on redirects and streaming decompressed-byte caps (0.8 MB RSS) |
mcp-python-sdk |
Python MCP SDK |
8 historical CVE sibling classes & 100,000-deep JSON |
0 |
Auto-armed loopback DNS-rebinding guard, 4 MiB body cap, and AES-256-GCM state tokens |
fastmcp |
Python MCP framework |
6 historical advisory classes probed live |
0 |
Verified fixes for OpenAPI SSRF, OAuth confused deputy, and cross-server token reuse |
twisted/twisted |
Python network engine |
6 DNS & HTTP framing suites (1,000-jump cap) |
0 |
Per-name visited-set DNS pointer guard and strict 400 disconnect on framing anomalies |

One self-refutation on vercel/next.js highlights why local probe execution is mandatory even on web frameworks. During source review, our auditing agent drafted a candidate Server-Side Request Forgery (SSRF) claim using a scoped IPv6 loopback zone literal (%eth0). When the agent ran its own verbatim probe against a local container instance of the vercel/next.js image-optimization pipeline, the attack failed closed. Both the WHATWG URL parser and ipaddr.js unwrapped the IPv4-mapped address and rejected the private range before any socket dialed. Without the E1 execution rule, that false positive would have produced a spurious report.
Applying sanitizer-gated auditing to enterprise supply-chain dependencies
Enterprise engineering teams can apply this same sanitizer verification loop as a proactive pre-merge control over third-party and vendored C dependencies.
When a security team audits an open-source dependency class externally, it can run three sibling checks in continuous integration before shipping any release artifact.
- Verifying NUL-termination guards on authentication packets. In C connection poolers, reading a client
PasswordMessageviamalloc(len)andmemcpy(len)without a trailingNULcheck risks heap over-reads. Downstreamstrlenor LDAP bind calls can then read past the buffer. Pre-merge sanitizer gates verify explicitNUL-termination bounds checks and safe buffer handling before merge (0memory over-reads). - Auditing CMake build pins and compiler flags. Static review of source files can miss how
CMakeLists.txtor container build scripts compile vendored C targets. Automated build checks verify that release flags preserve mandatory bounds guards and link against patched dependency revisions before any artifact ships. - Pairing automated internal gates with independent external certification audits. Under
ISO/IEC 42001(2023) governance (report 09, report 11), internal automated verification is necessary but never sufficient on its own. Enterprise teams should pair automated pre-merge sanitizer gates with independent externalISO/IEC 42001certification audits conducted by an accredited third-party certification body.
Coordinated vulnerability disclosure and embargo governance
Our harnesses produced 85 verified E1 execution proofs across 32 open-source projects, for which we prepared 31 private CVD packages (with 1 low-severity test-only finding excluded from advisory filing). For every confirmed finding, we follow Coordinated Vulnerability Disclosure (CVD) rules under ISO/IEC 29147 and ISO/IEC 30111.
- Zero public naming of unpatched targets. None of the 31 open-source repositories with active private disclosure reports are named in this study. All file paths, proof-of-concept inputs, and reproduction scripts remain strictly confidential until upstream maintainers publish fixes or the standard 90-day disclosure window closes.
- Minimal unified-diff patches included with every report. Maintainers of open-source projects are often volunteer-constrained. Each of our 31 private disclosure packages includes a minimal unified diff (
1to15lines of code). We compiled and verified every patch against itsE1harness (0post-patch sanitizer errors and100%test pass rate). - Channel verification before submission. Before sending any report, our workflow checks each repository's
SECURITY.mdpolicy. It routes findings through GitHub Private Vulnerability Reporting (PVR), security mailboxes, or maintainer-specified fix pull requests.
Security auditing antipatterns rejected by our gates
- Submitting unverified static LLM output (
E3) to maintainers (rejected after execution harnesses refuted26of32[81.3%] high-confidence static C/C++ claims). - Treating model verbalized confidence (
0.92) as proof of exploitability (rejected after a0.92-confidenceCWE-476claim onhaproxyreturnedrc = 0due to empty-string array sentinels). - Trusting container crash exit codes without signal and flag inspection (rejected after
2apparent crashes turned out to be-march=nativeSIGILLtraps inside the container hypervisor). - Filing duplicate advisories for documented threat-model exclusions or known issues (prevented by checking repository
SECURITY.md,THREAT_MODEL.md, and historical GHSA lineages before drafting any report). - Publishing vulnerability details before upstream patches ship (blocked by our 90-day CVD embargo across all
31private disclosure packages).
Pressure tests
Every finding was checked against the six standing fronts in Methods.
| front | what was tested | result |
|---|---|---|
| Specification | Unverified static model claims (E3) vs mandatory compiled execution proof (E1) |
E1 harnesses refuted 26 of 32 (81.3%) high-confidence static C/C++ claims before any disclosure was drafted |
| Aggregation | Pooled 68-repository finding counts vs stratified E1 (85), E2 (137), refuted (26), and cleared (10) ledger |
Prevented 137 unexecuted E2 source traces and 26 refuted claims from inflating confirmed vulnerability counts |
| Adjustment coarseness | Host -march=native container builds vs portable -O1 -fsanitize=address,undefined builds |
Caught 2 hypervisor SIGILL instruction traps that masqueraded as memory-corruption crashes |
| Prior work | Standalone static LLM benchmarks (Ullah et al., 2024) and fuzz-driver false crashes (Amusuo et al., 2025; Kim et al., 2025) | Confirmed that real-world entry-point reachability and caller bounds checks eliminate 81.3% of static false positives |
| Baseline sufficiency | Direct 38B reasoning across all 338 slices vs SemDeDup (cosine 0.85) plus local 4B single-pass triage |
Collapsed 338 slices to 245 clusters (-27.5%) in 76.8 ms and gated triage in 212 to 226 ms (0 output tokens) |
| Cross-sectional units | 28 automated C/C++ slicer campaigns vs 40 multi-language deep audits (Go, Rust, Python, TypeScript, C) |
Verified that the E1 execution requirement generalizes across memory-safe and memory-unsafe ecosystems (68 repos total) |
What this does not show
First, passing an adversarial probe battery (0 disclosable vulnerabilities across the 10 cleared targets) does not prove the absence of all bugs. Dynamic sanitizers and targeted protocol probes verify only the execution paths, build configurations, and threat models exercised by the harness.
Second, holding 137 code-level E2 source traces out of standalone CVD queues does not mean those code paths are risk-free. Many E2 findings represent genuine defense-in-depth gaps whose reachability depends on non-default deployment topologies or unexercised protocol states.
Third, local models do not replace human security engineers on threat-model judgment. Deciding whether a behavior violates a project's documented security boundary or represents intended operator functionality requires reading SECURITY.md and verifying live configuration defaults.
Reproduce
All aggregate metrics in this report and its three figures are stored in numbers.json, with SHA-256 integrity digests recorded in MANIFEST.md. In accordance with ISO/IEC 29147 coordinated vulnerability disclosure rules, target identities and reproduction harnesses for the 31 embargoed advisories are withheld until upstream remediation completes.
References
- Abbas, A., Tirumala, K., Simig, D., Ganguli, S., & Morcos, A. S. (2023). SemDeDup: Data-Efficient Learning at Web-Scale Through Semantic Deduplication. arXiv preprint. arXiv.
- Amusuo, P. C., Liu, D., Mendez, R. A. C., Metzman, J., Chang, O., & Davis, J. C. (2025). FalseCrashReducer: Mitigating False Positive Crashes in OSS-Fuzz-Gen Using Agentic AI. arXiv preprint. arXiv.
- Guo, J., Wang, C., Xu, X., Su, Z., & Zhang, X. (2025). RepoAudit: An Autonomous LLM-Agent for Repository-Level Code Auditing. Proceedings of ICML 2025. arXiv.
- ISO/IEC. (2018).
ISO/IEC 29147: Information Technology - Security Techniques - Vulnerability Disclosure. International Organization for Standardization. - ISO/IEC. (2019).
ISO/IEC 30111: Information Technology - Security Techniques - Vulnerability Handling Processes. International Organization for Standardization. - ISO/IEC. (2023).
ISO/IEC 42001(2023): Information Technology - Artificial Intelligence - Management System. International Organization for Standardization. - Kim, T., Han, H., Park, S., Jeong, D. R., Kim, D., Kim, D., et al. (2025). ATLANTIS: AI-Driven Threat Localization, Analysis, and Triage Intelligence System. arXiv preprint. arXiv.
- Li, Z., Dutta, S., & Naik, M. (2025). IRIS: LLM-Assisted Static Analysis for Detecting Security Vulnerabilities. Proceedings of ICLR 2025. arXiv.
- Li, Z.-Z., Zhang, D., Zhang, M.-L., Zhang, J., Liu, Z., Yao, Y., et al. (2025). From System 1 to System 2: A Survey of Reasoning Large Language Models. arXiv preprint. arXiv.
- Nie, Y., Li, H., Guo, C., Jiang, R., Wang, Z., Li, B., et al. (2025). VulnLLM-R: Specialized Reasoning LLM with Agent Scaffold for Vulnerability Detection. arXiv preprint. arXiv.
- Serebryany, K., Bruening, D., Potapenko, A., & Vyukov, D. (2012). AddressSanitizer: A Fast Address Sanity Checker. Proceedings of USENIX ATC 2012.
- Ullah, S., Han, M., Pujar, S., Pearce, H., Coskun, A., & Stringhini, G. (2024). LLMs Cannot Reliably Identify and Reason About Security Vulnerabilities (Yet?). Proceedings of IEEE Symposium on Security and Privacy (S&P 2024). arXiv.
- Zhang, C., Park, Y., Fleischer, F., Fu, Y.-F., Kim, J., Kim, D., et al. (2026). SoK: DARPA's AI Cyber Challenge (AIxCC): Competition Design, Architectures, and Lessons Learned. Proceedings of USENIX Security 2026. arXiv.
- Zhang, Y., Wang, J., Berzin, D., Mirchev, M., Liu, D., Arya, A., et al. (2024). Fixing Security Vulnerabilities with AI in OSS-Fuzz. arXiv preprint. arXiv.