Paper deep dive
CyberForge: Verified Vulnerability Injection at Repository Level for Cybersecurity Agent Training
Amine Lbath, Manan Suri, Aurelien Delaitre, Vadim Okun, Massih-Reza Amini, Ram D. Sriram, Dinesh Manocha
Intelligence
Status: succeeded | Model: Gemma-4-26B-A4B | Prompt: intel-v1 | Confidence: 94%
Last extracted: 8/10/2026, 2:25:12 AM
Summary
CyberForge is a framework for generating repository-level security training data by injecting vulnerabilities into real C/C++ projects. It uses fuzzer-guided and agentic in-context injection pipelines, validated by a differential proof-of-vulnerability (PoV) oracle. The resulting corpus of 1,034 validated vulnerabilities was used to fine-tune LLM agents (Gemma 4 variants), significantly improving performance on SEC-bench and generalizing to PatchEval.
Entities (8)
Relation Signals (6)
CyberForge â generalizesto â PatchEval
confidence 95% ¡ These gains generalize out of distribution to PatchEval
CyberForge â improvesperformanceon â SEC-Bench
confidence 95% ¡ Fine-tuning on trajectories collected over this corpus improves SEC-bench patch repair by +3.3 to +14.7 points
CyberForge â validatesusing â Differential PoV Oracle
confidence 95% ¡ a shared differential PoV oracle that requires the original and injected build to pass all tests and the PoV to trigger only on the injected build
Gemma-4 31B â isfinetunedby â CyberForge
confidence 92% ¡ We fine-tune three open students, Gemma 4 31B... under two teachers
GPT-5.4 Mini â isteacherfor â Gemma-4 31B
confidence 90% ¡ under two teachers, GPT-5.4-mini and Gemma 4 31B itself
CyberForge â uses â OSS-Fuzz
confidence 90% ¡ CyberForge targets C/C++ projects enrolled in OSS-Fuzz
Cypher Suggestions (0)
No Cypher suggestions yet.
Abstract
Abstract:Despite recent advances, frontier large language model (LLM) agents remain limited in discovering and patching complex vulnerabilities in real-world software. Generally available agents can already aid attackers, who only need to find one exploitable weakness, while defenders must continuously identify and patch all vulnerabilities across fast-growing codebases. Stronger defensive agents would help close this gap, yet the scarcity of security training data with reproducible build and execution environments remains a bottleneck. We present CyberForge, a framework that synthesizes executable, repository-level security training data by injecting vulnerabilities into real C/C++ projects. It validates each instance dynamically: the injected build must pass the project's unit tests, and generated proof-of-vulnerability (PoV) must trigger on the injected build and not on the clean one. CyberForge is not limited by the availability of disclosed vulnerabilities, therefore it can scale in comparison to data augmentation techniques which rely on historic CVE data. The resulting corpus holds 1034 validated vulnerabilities across 80 projects and 63 weakness categories, with edit locality similar to real CVE patches under a real-versus-real noise floor. Fine-tuning on trajectories collected over this corpus improves SEC-bench patch repair by +3.3 to +14.7 points, in all six configurations of three model scales and two teachers, with the 31B student reaching its GPT-5.4-mini teacher, 72.7% against 74.0%. These gains generalize out of distribution to PatchEval, a corpus containing other programming languages, where every configuration also improves and the 31B student passes its teacher.
Tags
Links
- Source: https://arxiv.org/abs/2608.06471v1
- Canonical: https://arxiv.org/abs/2608.06471v1
Trouble viewing inline? Open PDF directly â
Full Text
75,947 characters extracted from source content.
Expand or collapse full text
CyberForge: Verified Vulnerability Injection at Repository Level for Cybersecurity Agent Training Amine Lbath 1,2â , Manan Suri 1,3â , Aurelien Delaitre 1 , Vadim Okun 1 , Massih-Reza Amini 2 , Ram D. Sriram 1 , Dinesh Manocha 3 1 National Institute of Standards and Technology, 2 UniversitĂŠ Grenoble Alpes, CNRS, 3 University of Maryland, College Park Abstract Despite recent advances, frontier large language model (LLM) agents remain limited in discovering and patching complex vulnerabilities in real-world software. Generally available agents can already aid attackers, who only need to find one ex- ploitable weakness, while defenders must continuously iden- tify and patch all vulnerabilities across fast-growing code- bases. Stronger defensive agents would help close this gap, yet the scarcity of security training data with reproducible build and execution environments remains a bottleneck. We present CyberForge, a framework that synthesizes exe- cutable, repository-level security training data by injecting vulnerabilities into real C/C++ projects. It validates each in- stance dynamically: the injected build must pass the projectâs unit tests, and generated proof-of-vulnerability (PoV) must trigger on the injected build and not on the clean one. Cy- berForge is not limited by the availability of disclosed vul- nerabilities, therefore it can scale in comparison to data aug- mentation techniques which rely on historic CVE data. The resulting corpus holds 1 034 validated vulnerabilities across 80 projects and 63 weakness categories, with edit locality sim- ilar to real CVE patches under a real-versus-real noise floor. Fine-tuning on trajectories collected over this corpus improves SEC-bench patch repair by +3.3 to +14.7 points, in all six configurations of three model scales and two teachers, with the 31B student reaching its GPT-5.4-mini teacher, 72.7 % against 74.0 %. These gains generalize out of distribution to PatchEval, a corpus containing other programming languages, where every configuration also improves and the 31B student passes its teacher. Code and data are available at https://cyb3rforge.github.io. 1 Introduction Agentic systems have started finding real vulnerabilities. An- thropicâs Mythos reported thousands of zero-day findings across operating systems and browsers (Anthropic 2026) and most recently, OpenAI disclosed that models under evalua- tion autonomously found and chained zero-days into a re- â These authors contributed equally. Disclaimer: Certain trade names and company products are men- tioned in the text or identified. In no case does such identification i mply recommendation or endorsement by the National Institute of Standards and Technology (NIST), nor that they are necessarily the best available for the purpose. mote code execution path on Hugging Faceâs production in- frastructure (OpenAI 2026). On repository-level benchmarks that ask a model to locate a weakness in a real codebase and demonstrate it with an executable proof-of-vulnerability (PoV), even the strongest systems remain limited (Anthropic 2026; Wang et al. 2026a; Lee et al. 2025). The imbalance this creates favors attackers. An attacker needs one exploitable weakness and can retry indefinitely; a defender has to continuously secure an entire codebase. The balance shifts back only when automated detection and repair become dependable (Potter et al. 2025; Zhuo et al. 2026). Developing such capability in models that defenders can deploy and adapt is the goal of this work. Availability of training data is the binding constraint (Pot- ter et al. 2025; Zhuo et al. 2025a). Software-engineering agents benefited from datasets of packaged repositories with reproducible build and test environments, producing thou- sands of runnable instances and double-digit gains (Jimenez et al. 2024; Pan et al. 2025; Yang et al. 2025; Jain et al. 2025). Security-agent training lacks a comparable pipeline because its validation problem is more complex. Functional bugs are exposed by tests: the buggy version fails at least one test that the fixed version passes. A vulnerability must instead re- main latent under existing tests and normal execution while still being triggerable by adversarial input through a PoV that succeeds only on the vulnerable version. Automating this dual validation at scale, without a human expert in the loop, is what makes security data synthesis harder than its software-engineering analogue. Existing runnable vulnerability datasets are assembled from disclosed Common Vulnerabilities and Exposures (CVEs) and bug-bounty reports, and are mostly built to eval- uate rather than to train (Lee et al. 2025; Wang et al. 2026b; Zhang et al. 2025; Ullah et al. 2025). Each disclosure has to be turned into an instance by reconstructing a historical environment, locating the vulnerable state, and recovering a working PoV. Manual setup does not scale, automated replay succeeds only in part (Wang et al. 2026b; Lee et al. 2025). More fundamentally, these resources remain limited by the rate of human vulnerability discovery and public disclosure. Capture-the-flag tasks avoid that dependency but are built in idealized settings and transfer poorly to real software (Wang et al. 2026b; Zhu et al. 2025). Function-level injection tech- niques can be used to train LLMs to become vulnerability arXiv:2608.06471v1 [cs.CR] 6 Aug 2026 Table 1: Comparison of CyberForge with related work. Synthetic injection exists at function granularity (VGX, AVIATOR, ProSec) but targets detection models rather than agents and validates without execution. Existing project-level resources are evaluation artifacts whose growth is limited by the rate of public disclosure. No prior system supplies project-level training data from synthetic injection validated by execution. SystemPurposeScopeTasksBounded by disclosure Validation VGX (Nong et al. 2023)Vuln. detection Function DetectionĂStatic AVIATOR (Lbath et al. 2026)Vuln. detection Function DetectionĂStatic ProSec (Xu et al. 2025)Secure gen.Function AlignmentĂStatic CTF-Dojo (Zhuo et al. 2025b)TrainingCTFExploitationâExecution CyberZero (Zhuo et al. 2025a)TrainingCTFExploitationâSimulation SEC-bench (Lee et al. 2025)EvaluationProject PoV, patchâCVE replay CyberGym (Wang et al. 2026b) EvaluationProject ExploitationâCVE replay BountyBench (Zhang et al. 2025) EvaluationProject Detect, exploit, patchâBug bounty CVE-Genie (Ullah et al. 2025)EvaluationProject ExploitationâCVE replay CVE-Factory (Luo et al. 2026)TrainingProject PatchâAutomated CVE replay CyberForge (ours)TrainingProject PoV, patchĂDifferential PoV detectors, but transfer badly to realistic project level settings (Risse and BĂśhme 2024; Ding et al. 2024; Lbath et al. 2026). We introduce CyberForge, a scalable framework for gen- erating executable, repository-level, PoV-validated security training data from real-world C/C++ projects. CyberForge creates new training instances by injecting candidate weak- nesses into existing codebases. Rather than mining historical disclosures, this framework decouples corpus growth from the rate of human discovery and disclosure, while preserving the properties needed for agent training: realistic codebases, reproducible build and execution environments, and end-to- end PoV validation. CyberForge implements two complementary pipelines. Fuzzer-guided injection uses OSS-Fuzz (Google 2016) cov- erage to find sites reachable by an existing harness, so val- idation can lean on the harness itself. Agentic in-context injection synthesizes weaknesses beyond harness reach. It combines a workflow of autonomous agents, static analysis tools, in-context examples, and iterative retry to synthesize and validate vulnerabilities end-to-end. Each instance op- erates on reproducible containerized environments derived from OSS-Fuzz images and is checked by a differential PoV oracle that requires the original and injected build to pass all tests and the PoV to trigger only on the injected build. Across 80 C/C++ projects CyberForge produced 1 034 validated vulnerabilities spanning 63 weakness categories. We fine-tune three open students, Gemma 4 31B, 12B and E4B (Google DeepMind 2026), under two teachers, GPT- 5.4-mini and Gemma 4 31B itself. All six configurations improve SEC-bench patch repair, by +3.3 to +14.7 points; the strongest raises the 31B student from 58.0 % to 72.7 %, comparable to the GPT-5.4-mini teacher that supervised it. The same training transferred to Go, JavaScript and Python repair on PatchEval, while the training corpus contains none of those languages. Contributions: ⢠A repository-level generation framework. CyberForge synthesizes cybersecurity-agent training data from build- able codebases through vulnerability injection and differ- ential PoV validation, with two complementary pipelines. ⢠Validated corpus of project level vulnerabilties. 1 034 instances over 80 projects and 63 categories, with edit locality inside the noise floor separating two real CVE corpora. ⢠Downstream performance improvements. SEC-bench score improves in all six studentâteacher configurations, by +3.3 to +14.7 points, and the gains hold on PatchEval, an out-of-distribution cross-language benchmark. 2 Related Work Table 1 compares CyberForge with prior vulnerability- generation, training and evaluation systems. SWE-bench (Jimenez et al. 2024) established repository- level evaluation from real pull requests, and SWE-Gym (Pan et al. 2025), SWE-Smith (Yang et al. 2025) and R2E- Gym (Jain et al. 2025) turned the same idea into training data by synthesizing bugs inside runnable environments. SWE- Smith is the closest analogue to our injection pipeline, but its oracle does not apply to our case. It accepts an injection once a unit test fails, which signals that a functional bug was introduced. Our criterion is the opposite: the injected build must still pass every unit test, and the weakness may surface only under a PoV input that leaves the clean build unaffected. Cyber-Zero (Zhuo et al. 2025a) synthesizes agent trajec- tories without executable environments, simulating runtime feedback from CTF writeups. CyberForge keeps execution in the loop, so every trajectory is grounded in a build that actually compiles and a PoV that actually triggers. SEC-bench (Lee et al. 2025), CyberGym (Wang et al. 2026b), BountyBench (Zhang et al. 2025) and CVE- Genie (Ullah et al. 2025) assemble runnable instances from disclosed vulnerabilities. They are evaluation artifacts, rather than scalable training pipelines, and remain limited by the supply of publicly disclosed vulnerabilities VGX (Nong et al. 2023) and AVIATOR (Lbath et al. 2026) inject weaknesses at function granularity to train detectors, validating statically or with learned filters rather than by ex- ecution. Neither produces a runnable project, and function- level supervision has transferred poorly to realistic detec- tion (Risse and BĂśhme 2024; Ding et al. 2024). CyberForge injects into repository-level buildable projects and dynami- cally validates instances. Figure 1: Overview of CyberForge. Two injection pipelines synthesize candidate vulnerable/patch pairs from OSS-Fuzz C/C++ projects; a shared differential PoV oracle admits a pair only if the injected build passes the projectâs tests and the PoV triggers on it alone; a teacher model collects verified trajectories for supervised fine-tuning. 3 CyberForge Figure 1 presents CyberForge, an end-to-end vulnerabil- ity injection framework, that includes two complementary pipelines: 1) Fuzzer-guided Injection, which utilizes fuzzer metadata to prompt an LLM agent to inject the vulnerability, and 2) In-context Agentic Injection, which performs itera- tive injection in a specialized agent workflow. The generated vulnerabilities are validated using a differential oracle, af- ter which the injections are used to mine teacher trajectories using capable models. 3.1 Project Setup Source and scope. CyberForge targets C/C++ projects en- rolled in OSS-Fuzz (Google 2016). Two properties motivate the choice. Memory-safety defects, prevalent in these pro- gramming languages, remain the dominant class of critical CVEs in systems software (Xin et al. 2025), and OSS-Fuzz ships per-project Docker images with build scripts, sanitizer configuration and libFuzzer harnesses, which gives repro- ducible environments without per-project engineering. Environment construction and qualification. For each candidate project, we build a container with a compiled bi- nary, ASAN (Serebryany et al. 2012) and UBSAN (LLVM Project 2026) instrumentation, and the projectâs existing har- nesses. No project-specific build logic is written, and every step is delegated to the projectâs preexisting build.sh. A project enters the pool only if its tests build and run unat- tended, pass at a 100 % rate on the unmodified codebase, with identical results across five runs. Projects with flaky tests are rejected. This process retained 100 qualified projects, 80 of which eventually contributed at least one validated instance. 3.2 Vulnerability Injection Pipeline 1: Fuzzer-Guided Injection This pipeline uses the existing fuzzer infrastructure of each OSS-Fuzz project to identify high-value injection sites, code locations that are both security-relevant and reachable by an existing libFuzzer harness, and then validates injections automatically, elimi- nating the need for a manually written PoV. Step 1: Reachability extraction. For each project, we parse the offline OSS-Fuzz metadata cache, combining Fuzz Introspector reports, which summarize per-fuzzer reachabil- ity and coverage, with harness definitions and per-fuzzer cov- erage statistics to construct a reachability map of all functions reachable from at least one fuzzing harness. Step 2: Candidate scoring and selection. Each reachable function is scored along two axes and ranked by a weighted combination of these scores. The first is a function score based on reachability kind (runtime vs. static), structural role (e.g., parser entry point, buffer writer, decoder conversion, container access), call depth, fanout (the number of functions it directly calls), and file coverage. The second is a trigger- ability score estimating how likely an injected fault at that site can be reached and triggered by an existing harness, using parser proximity, path signal strength, guard-to-sink distance (i.e., the proximity between a safety check and the operation it protects), and blocker proximity (i.e., the presence of nearby checks that may prevent malformed inputs from reaching the candidate site). Candidates are further diversified by capping per-file density and round-robin selecting across harness, role, and vulnerability category buckets to avoid duplication. Each selected candidate is annotated with an inferred weak- ness type (e.g., removed bounds check, unchecked index, copy-size constraint removal) and a confidence tier. Step 3: LLM injection agent. The agent is given the candi- date function, the precise site location and downstream oper- ation within it, the inferred vulnerability category, the harness context, and the input format family (e.g., font binary, ZIP archive, UTF-16 text) derived from the harness subsystem. It also receives vulnerability-category-specific edit guidance specifying allowed modifications (e.g., operator widening, off-by-one bound change) and hard constraints (e.g., no new branches, single-file edit, preserve the downstream opera- tion). The agent introduces one minimal, targeted modifica- tion that weakens the existing security check at the identified location. The modified project is compiled and run against unit tests; if either fails, the agent is prompted to retry. Step 4: PoV generation and fuzzer-based validation. Once the injection passes unit tests, the agent produces a PoV script that exercises the injected fault. The PoV is guided by the input format context: the agent is provided with the in- put model, preferred seed extensions, and PoV-writing con- straints derived from the harness. Given this context, the agent must demonstrate the vulnerability via a determinis- tic one-shot execution rather than open-ended fuzzing. This PoV is validated immediately by the shared differential PoV verifier (§3.3). As a complementary validation path, a post-hoc libFuzzer run is also executed against the injected build. The run uses a format-aware seed corpus: format-specific input generators produce seeds matched to the harnessâs input model (e.g., GSUB table mutations for font parsers, ZIP header mutations for archive handlers), which are first replayed individually and then used to seed a timed libFuzzer run. Any input found by the fuzzer that triggers the vulnerable behavior on the new build is recorded as an additional confirmed PoV. Injections for which neither the agent PoV nor the fuzzer produces a trigger unique to the injected build are discarded. Pipeline 2: Agentic In-Context Injection This pipeline complements the other by synthesizing new vulnerabilities beyond those reachable by existing fuzz harness, drawing on candidate sites from two complementary selection strategies. Candidate selection by hybrid retrieval. The first strat- egy matches the target project against the PrimeVul dataset of C/C++ functions containing historical CVEs (Ding et al. 2024), combining structural and semantic similarity retrieval (Luan et al. 2021; Cambronero et al. 2019). A structural retriever compares functions by the n-grams of their AST node-type sequences (Jiang et al. 2007), so that matches re- flect code topology rather than identifier names. A semantic retriever compares dense embeddings of the function text by cosine similarity. Their ranked lists are merged by re- ciprocal rank fusion (Cormack, Clarke, and BĂźttcher 2009). A lightweight reranking step then demotes trivial accessor functions and isolated, uncalled helper functions. Each re- tained match supplies both an injection site in the target project and an aligned example pair (secure, vulnerable) that serves as the in-context template for the injection. Candidate selection by agentic exploration. The second strategy lets specialist LLM agents explore the codebase di- rectly, broadening diversity beyond sites that match known CVE patterns. A planner LLM splits a candidate budget across specialists, each responsible for one family of weak- nesses, according to how relevant each family is to the project. Their proposals are then pooled, deduplicated, and ranked by an LLM score estimating how plausible, reachable, and project-relevant each proposed vulnerability is. Injection stage. Each injection target is specified by the selected code location, the Common Weakness Enumeration (CWE) type, and its call chain and dataflow, recovered with the static-analysis tool CodeQL (GitHub 2024). The agent modifies the project to introduce the vulnerability and pro- duces an injection description. The modified project is then compiled and run against unit tests. Compilation or test fail- ures trigger a revision loop back to this stage. Taint analysis and PoV generation. The project is then analyzed using agent-based taint analysis to identify dataflow paths through which attacker-controlled input can reach the injected vulnerable location, providing valuable context on how to trigger the vulnerability. The PoV generation stage then constructs a proof-of-vulnerability using available sig- nals: ASAN/UBSAN sanitizer reports, observable failure be- havior, side effects (file writes, memory leaks), and output differences between the vulnerable and clean builds. Verification and retry. The generated PoV is passed to a verifier, which runs the differential PoV oracle, and checks that the observed behavior is attributable to the injected vul- nerability, with the sanitizer reporting the expected type of error at the expected code location, not an unrelated or spu- rious failure. If verification succeeds, the vulnerable code, its PoV, and the sanitizer report are saved. Otherwise, the loop retries PoV generation; after a fixed number of retries it loops back to the injection stage for a fresh injection. 3.3 Differential Validation Both pipelines converge on a shared validation criterion. Condition 1: Passing unit tests. A valid injection must not break any existing unit tests on the vulnerable build, as it must be latent: present in the code but not triggered by normal execution paths, reflecting the nature of real-world security weaknesses that survive production testing and code review. Condition 2: Differential PoV validation. The PoV must trigger on the injected build and not on the clean build under identical input. The condition validates injection and PoV jointly, since neither is meaningful without the other. 3.4 Task Formation and Training Task construction matches SEC-bench (Lee et al. 2025), fol- lowing the same methodology as (Luo et al. 2026), so that training and evaluation align. The pipeline records full inter- action traces from an agent running on this task in autonomy inside the generated dataset. Success is decided by the differ- ential oracle of §3.3 rather than by the agentâs own report, so a trajectory that claims success without passing validation is discarded like any other failure. Applying the methodology from (Pan et al. 2025; Luo et al. 2026), only the successful trajectories are then used to train a model. 4 Experimental Setup Trajectory Collection For teacher trajectory extraction we used Mini-SWE-Agent (SWE-agent Team 2024), as a Table 2: CyberForge, trained at different scales, with different teachers evaluated on SEC-bench (C/C++; in-domain), and PatchEval (Py, JS, Go; out-of-domain). SEC-benchPatchEval Model(%)Strict (%) PoV (%) Teachers (reference) GPT-5.4-mini74.013.015.2 Gemma 4 31B58.012.214.4 Gemma 4 E4B (base)6.02.63.9 CyberForge-E4B10.7â4.75.2â2.6 6.5â2.6 Gemma 4 31B teacher CyberForge-E4B9.3â3.39.1â6.5 10.4â6.5 GPT-5.4-mini teacher Gemma 4 12B (base)8.73.93.9 CyberForge-12B16.0â7.36.1â2.2 8.7â4.8 Gemma 4 31B teacher CyberForge-12B16.7â8.0 12.8â8.9 14.1â10.2 GPT-5.4-mini teacher Gemma 4 31B (base)58.012.214.4 CyberForge-31B64.7â6.7 12.4â0.2 15.7â1.3 Gemma 4 31B teacher CyberForge-31B72.7â14.7 14.8â2.6 16.5â2.1 GPT-5.4-mini teacher lightweight agentic scaffold. To prevent corrupting the run, the execution stays inside the projectâs OSS-Fuzz container with no network access, and no access to the reference patch, so it cannot recover the answer it is being trained to derive. Models and training. We fine-tune three open students, Gemma 4 31B, 12B and E4B (Google DeepMind 2026), under two teachers: Gemma 4 31B itself, giving a self- distillation setting, and GPT-5.4-mini as a stronger teacher. Every run uses the same recipe and the same agentic scaffold at train and test time. We train LoRA adapters (r=32, Îą=64, dropout 0.05), at learning rate 1Ă10 â4 for three epochs on one H200. Evaluation. The main benchmark is SEC-bench (Lee et al. 2025), with 150 instances from 24 projects, evaluating patch success rates. We also evaluated on PatchEval (ByteDance Security Research 2025), as an out-of-distribution test, with 230 instances in Go, JavaScript and Python, none of which appear in our C/C++ corpus. 5 Results 5.1 Fine-Tuning on CyberForge Trajectories Over the 1 034 generated instances, we collected agent tra- jectories from two teachers: 1 194 accepted trajectories from GPT-5.4-mini vs. 880 from Gemma 4 31B. Table 2 reports the performance of students trained on these trajectories. Benchmark evaluation. On SEC-bench, all six studentâ teacher pairs gain from +3.3 to +14.7 points. The largest gain comes from Gemma 4 31B under a GPT-5.4-mini teacher, from 58.0 % to 72.7 %, within 1.3 points of the teacher. The Gemma 4 12B student roughly doubles from 8.7 % to 16.7 %. 220440880 training trajectories 0 8 16 SEC-bench score (%) 12B base 3.6 12.1 16.0 Figure 2: Training data scaling evaluated on SEC-bench. Self-distillation and stronger teacher. On PatchEval the GPT-5.4-mini students beat the self-distilled ones at every scale, by 2.4 to 6.7 points. On SEC-bench the advantage grows with scale: 8.0 points at 31B, 0.7 at 12B, and at E4B it reverses, the Gemma teacher reaching 10.7 % against 9.3 %, both still beating their 6.0 % base. Notably, self-distillation helps at every scale, so the corpus carries signal that does not depend only on teacherâs capabilities, paving the way for strong models learning from their own trajectories extracted through our workflow. Fine-tuning steers task resolution toward the teacher. Figure 3 splits each instance a student solves by where the ability came from: the student could already solve it before fine-tuning, its teacher can solve it, or neither can. Every student is steered in varying degree toward tasks its teacher can specifically solve. E4B is steered entirely onto them: all 14 of its solutions are ones the teacher also solves, and none of the nine its base solved survive, yet it picks up only 14 % of what the teacher can do and its base cannot. 31B gives up almost nothing, keeping 79 of its baseâs 87, and picks up 62 %, with 12B in between at 31 % kept and 18 % picked up. The smallest student is therefore steered the furthest and gains the least from it, which points to student capacity rather than the corpus as the limit. At 31B the student also moves past both sources, solving 10 instances that neither its base nor its teacher solves. transfer 14% ¡ kept 0% Gemma 4 E4B 1 089 08 14 0 transfer 18% ¡ kept 31% Gemma 4 12B 0 380 09 18 4 transfer 62% ¡ kept 91% Gemma 4 31B 1 1012 77 20 72 baseCyberForge studentGPT-5.4-mini teacher Figure 3: Analysis of teacher transfer, and base retention on SEC-bench. The two teachers produce complementary students. Because the two students differ in which instances they solve, running both and keeping the successful run, recovers far more than either alone. Computed post hoc over the same runs and at the cost of a second inference pass, this ensemble scoring reaches 18.0, 25.3 and 82.0 % at E4B, 12B and 31B, 7.3 to 9.3 points above the better single student at every scale. The complementarity is significant enough to be worth more than scale or supervision: two E4B students beat the best sin- gle 12B student, 18.0 against 16.7 %, and two 31B students beat the teacher that trained them, 82.0 against 74.0 %. The gains transfer out of distribution. PatchEval holds 230 CVEs in Go, JavaScript and Python, disjoint from the C/C++ training corpus, and scores each patch under a strict criterion and a PoV-blocking one. Every teacherâstudent pair improves on both: the 12B student by +8.9 strict and +10.2 PoV, and the 31B student reaches 14.8 % strict against the teacherâs 13.0 %. This indicates that our training data enabled the model to generalize the concepts, rather than learning language-specific knowledge. Performance scales with corpus size. In Figure 2, the number of training trajectories varies, holding the student (Gemma 4 12B), the teacher (Gemma 4 31B) and the LoRA recipe fixed. Scores rise monotonically, from 3.6 to 12.1 to 16.0 % as the corpus doubles twice, with no sign of saturation at 880 trajectories. Importantly, at 220 trajectories the student scores below its own base model, so a corpus too small to teach the workflow is worse than no fine-tuning at all. Table 3: Workflow ablation for Pipeline 2. ConfigurationInjected Validated Naive single pass68.20.0 Taint analysis only75.52.8 Retry loops only77.63.5 Full workflow77.67.5 5.2 Generated Corpus CyberForge made 16 172 injection attempts, of which 1 034 passed validation over 80 projects and 63 weakness cate- gories. Writing a plausible injection is easy; producing one the differential oracle accepts is the hard part. Table 3 ab- lates Pipeline 2: a naive single-pass agent already compiles and passes unit tests in 68.2 % of attempts, yet none of these pass validation, and the full workflow lifts the rate of plau- sible injections to 77.6 % while taking validated yield from 0 % to 7.5 %. Pipeline 1 shows the same from the validation side: a post-hoc fuzz-replay stage raises yield substantially with the injection stage untouched. The gain comes from the machinery around the injection, not from better injections. P1 10,967 P2 5,205 Validated 1,034 Build/apply (3,696) No patch (2,064) Other (injection) (760) PoV never fires (6,203) PoV on clean too (1,508) Other (validation) (907) Figure 4: Analysis of the Cyberforge data generation pipeline. Figure 4 shows that the two pipelines fail at different stages: Pipeline 1 loses 64.2 % of its candidates at the validation stage and Pipeline 2 58.8 % at injection. A PoV that never triggers is the largest single cause of failure in both pipelines (44.6 and 33.1 %). Pipeline 2 additionally fails three times as often at producing a usable patch (24.2 % against 8.7 %), as its injection sites go beyond fuzzer reachability. We measured how closely the released instances resemble the real CVE patches in SEC-bench (Lee et al. 2025), us- ing the two-sample KolmogorovâSmirnov distance (Smirnov 1948) over the functions an edit touches. The distance is 0.165, against a 0.190 floor measured between two real CVE corpora, which supports the claim our injected vulnerabilities are near-realistic. The protocol is included in the supplement. 5.3 How Fine-Tuning Changes Agent Behavior Each agent turn is one shell command, and a command can do several things at once, so a turn can take more than one label: explore, edit, verify, or the combination edit+verify, which we treat as its own state. Workflow coverage c is the share of instances on which a verify occurs at or after an edit. Step budgets differ across runs, so every turn-indexed quantity uses the first 30 turns, the largest common horizon. Students move toward their teacherâs behavior. Figure 6 compares each runâs trajectory behavior between the base and fine-tuned model. Three of the four metrics measure the same thing: whether the agent finishes an editâ verify cycle and returns something gradeable. Fine-tuning improves all three: each moves toward the teacherâs value, the star, at every scale but one, E4B under the GPT teacher, which stays flat on the verified-final rate and still emits malformed output on 12.7 % of instances. The fourth, atomic edit+verify, tracks which teacher supervised the student, not its scale. basetuned 20 40 60 % of 150 SEC-bench score â better basetuned 25 50 75 100 % of 150 Workflow coverage c â better basetuned 25 50 75 100 % of 150 Verified-final rate â better basetuned 0 10 20 % of 150 Format-error rate â better basetuned 0 10 20 % of 150 Empty-patch rate â better basetuned 20 40 % of turns Atomic edit+verify no preferred direction GPT-5.4-mini (reference) Gemma 4 31B teacher GPT-5.4-mini teacher Gemma 4 E4B Gemma 4 12B Gemma 4 31B Figure 6: Visualization of behavorial metrics comparing the base models (open markers) against fine-tuned CyberForge models (filled), with teacher models as anchors. 0 50 100 0 50 100 0 50 100 11530 0 50 100 1153011530 0 75 150 0 75 150 0 75 150 0 75 150 base Gemma 4 31BGPT-5.4-mini E4B 12B 31B Teacher Models Base Models / Student Models distribution of actions (%) trajectories still active exploreeditverifyedit+verifyothertrajectories still activefewer than 10 active Figure 5: Analysis of coarse agent action behavior over 30 turns, demonstrating transfer of agent action density from teacher models to respective Cyberforge student models Two independent channels. The SEC-bench score de- composes exactly as score = cq v + (1â c)q u , with q v the solve rate among instances that reached an editâ verify cy- cle and q u the rate among the rest. The two terms move independently and in opposite directions across scales. At 12B coverage quadruples, 20.7 â 82.7 %, while q v is flat, so the gain comes entirely from the model reaching the verifi- cation stage. At 31B coverage is already saturated and barely moves, 92.7 â 100.0 %, while q v rises 10.1 points. The same training repairs whichever channel was broken. The 12B base edits without verifying. The mechanism behind the coverage gap is visible turn by turn (Figure 5). The 12B base model spends its trajectory issuing edit com- mands, a median of 14 per trajectory among those that edit at all, while completing an editâ verify cycle on 20.7 % of instances with a median of zero such cycles. It edits blindly and never checks its work, and its active count falls fastest of any run. Both of its fine-tunes acquire the verification band, and format violations collapse from 38 instances to 2 under the Gemma teacher and 0 under the GPT teacher. Batching is a teacher fingerprint. GPT-5.4-mini writes and tests in a single command in 51 % of its turns, where base models do so in 7 to 11 % of theirs. Students distilled from it move toward it, 12B from 7 to 55 % and 31B from 9 to 22 %, while the Gemma-teacher students at the same scale do not. At 31B, the student taught by GPT closes the gap with its teacher in behavior space as well as in score (c = 100.0 against 98.7 %, q v = 72.7 against 74.3 %): distillation transferred the workflow, not merely the accuracy. 6 Conclusion We presented CyberForge, which builds security training data by injecting weaknesses into real C/C++ projects. In- stances are verified through execution: the injected build must pass the projectâs own tests, and the proof of vulnerability must trigger on it but not on the clean build. Instances are cre- ated rather than mined, so corpus growth is decoupled from the rate of public disclosure. Across 80 OSS-Fuzz projects the two pipelines produced 1 034 validated instances in 63 weakness categories, and the functions their edits touched are distributed about as locally as those of real vulnerabilities. Training on trajectories collected over this corpus im- proved SEC-bench in all six studentâteacher configurations, by +3.3 to +14.7 points, with the 31B student reaching 72.7 % against its teacherâs 74.0 %. The gains transfer across languages: every configuration also improved on PatchEval, which is entirely Go, JavaScript and Python while the train- ing corpus is entirely C/C++. CyberForge gives defenders a scalable source of execution-validated data for training their own security agents. Ethical Statement CyberForge aims to close the training-data gap on the defen- sive side of AI-assisted security. All injected vulnerabilities are synthetic modifications of open-source code, not previ- ously unknown bugs in deployed software. Models fine-tuned on CyberForge trajectories have improved cybersecurity ca- pabilities. Our framework does not produce an exploit to actively operationalize a weakness and compromise a sys- tem. Instead, it generates a proof of vulnerability (PoV) that demonstrates a weakness exists and is reachable, without de- livering a malicious payload. We note that similar capabilities already exist in other models; our contribution is to study the role of targeted training data, not to introduce capabilities that do not otherwise exist. References Anthropic. 2026. Claude Mythos Preview. https://red. anthropic.com/2026/mythos-preview/. Accessed: May 2026. ByteDance Security Research. 2025. PatchEval: A Multi- Language Benchmark for Automated Vulnerability Repair. arXiv preprint arXiv:2511.11019. Cambronero, J.; Li, H.; Kim, S.; Sen, K.; and Chandra, S. 2019. When Deep Learning Met Code Search. In Proceed- ings of the 2019 27th ACM Joint Meeting on European Soft- ware Engineering Conference and Symposium on the Foun- dations of Software Engineering (ESEC/FSE), 964â974. Cormack, G. V.; Clarke, C. L. A.; and BĂźttcher, S. 2009. Reciprocal Rank Fusion Outperforms Condorcet and Indi- vidual Rank Learning Methods. In Proceedings of the 32nd International ACM SIGIR Conference on Research and De- velopment in Information Retrieval, 758â759. Ding, Y.; Fu, Y.; Ibrahim, O.; Sitawarin, C.; Chen, X.; Tizpaz- Niari, S.; Millstein, T.; Ray, B.; and Wang, Y. 2024. Prime- Vul: Vulnerability Detection with Code Language Models at Industry Scale. In IEEE Symposium on Security and Privacy (S&P). GitHub. 2024. CodeQL. https://codeql.github.com/. Ac- cessed: 2026-06-28. Google. 2016. OSS-Fuzz: Continuous Fuzzing for Open Source Software. https://github.com/google/oss-fuzz. Google DeepMind. 2026. Gemma 4. https://deepmind. google/models/gemma/gemma-4/. Accessed: 2026-07-01. Jain, N.; et al. 2025. R2E-Gym: Procedural Environ- ments and Hybrid Verifiers for Scaling Open-Weights SWE Agents. In Conference on Language Modeling (COLM). ArXiv:2504.07164. Jiang, L.; Misherghi, G.; Su, Z.; and Glondu, S. 2007. DECKARD: Scalable and Accurate Tree-Based Detection of Code Clones. In Proceedings of the 29th International Conference on Software Engineering (ICSE), 96â105. Jimenez, C. E.; Yang, J.; Wettig, A.; Yao, S.; Narasimhan, K.; and Press, O. 2024. SWE-bench: Can Language Models Resolve Real-World GitHub Issues? In International Con- ference on Learning Representations (ICLR). Lbath, A.; Amini, M.-R.; Delaitre, A.; and Okun, V. 2026. AVIATOR: Towards AI-Agentic Vulnerability Injec- tion Workflow for High-Fidelity, Large-Scale Code Security Datasets. arXiv preprint arXiv:2508.20866. Lee, H.; et al. 2025. SEC-bench: Automated Benchmark- ing of LLM Agents on Real-World Software Security Tasks. arXiv preprint arXiv:2506.11791. LLVM Project. 2026. UndefinedBehaviorSanitizer. https: //clang.llvm.org/docs/UndefinedBehaviorSanitizer.html. Clang documentation. Accessed: 2026-07-01. Luan, Y.; Eisenstein, J.; Toutanova, K.; and Collins, M. 2021. Sparse, Dense, and Attentional Representations for Text Re- trieval. Transactions of the Association for Computational Linguistics (TACL), 9: 329â345. Luo, X.; Zhang, J.; Zhou, S.; Huang, R.; Xiao, C.; Zhu, Q.; Ma, Z.; Yue, X.; Yue, Y.; Zeng, W.; and Che, W. 2026. CVE-Factory: Scaling Expert-Level Agentic Tasks for Code Security Vulnerability. In Proceedings of the 43rd International Conference on Machine Learning (ICML). ArXiv:2602.03012. Nong, Y.; Fang, R.; Yi, G.; Zhao, K.; Luo, X.; Chen, F.; and Cai, H. 2023. VGX: Large-Scale Sample Generation for Boosting Learning-Based Software Vulnerability Analyses. arXiv preprint arXiv:2310.15436. OpenAI. 2026. OpenAI and Hugging Face part- ner to address security incident during model eval- uation.https://openai.com/index/hugging-face-model- evaluation-security-incident/. Accessed: 2026-07-28. Pan, J.; Wang, X.; Neubig, G.; Jaitly, N.; Ji, H.; Suhr, A.; and Zhang, Y. 2025. Training Software Engineering Agents and Verifiers with SWE-Gym. In International Conference on Machine Learning (ICML). ArXiv:2412.21139. Potter, Y.; Guo, W.; Wang, Z.; Shi, T.; Li, H.; Zhang, A.; Kelley, P. G.; Thomas, K.; and Song, D. 2025. Frontier AIâs Impact on the Cybersecurity Landscape. arXiv preprint arXiv:2504.05408. Risse, N.; and BĂśhme, M. 2024. Top Score on the Wrong Exam: On Benchmarking in Machine Learning for Vulnera- bility Detection. arXiv preprint arXiv:2408.12986. Serebryany, K.; Bruening, D.; Potapenko, A.; and Vyukov, D. 2012. AddressSanitizer: A Fast Address Sanity Checker. In Proceedings of the 2012 USENIX Annual Technical Con- ference (USENIX ATC 12), 309â318. USENIX Association. Smirnov, N. 1948. Table for Estimating the Goodness of Fit of Empirical Distributions. The Annals of Mathematical Statistics, 19(2): 279â281. SWE-agent Team. 2024. mini-swe-agent: The 100 line AI agent that solves GitHub issues. https://github.com/SWE- agent/mini-swe-agent. GitHub repository. Ullah, S.; Balasubramanian, P.; Guo, W.; Burnett, A.; Pearce, H.; Kruegel, C.; Vigna, G.; and Stringhini, G. 2025. From CVE Entries to Verifiable Exploits: An Automated Multi- Agent Framework for Reproducing CVEs. arXiv preprint arXiv:2509.01835. Wang, Z.; Schiller, N.; Li, H.; He, J.; Holz, T.; and Song, D. 2026a. ExploitGym: Can AI Agents Turn Security Vulnera- bilities into Real Attacks? arXiv preprint arXiv:2605.11086. Wang, Z.; Shi, T.; He, J.; Cai, M.; Zhang, J.; and Song, D. 2026b. CyberGym: Evaluating AI Agentsâ Real-World Cybersecurity Capabilities at Scale. arXiv:2506.02548. Xin, Z.; Cao, S.; Sun, X.; and Lo, D. 2025. Large Language Model for Vulnerability Detection and Repair: Literature Re- view and the Road Ahead. ACM Transactions on Software Engineering and Methodology, 34(5): Article 145. Xu, X.; Su, Z.; Guo, J.; Zhang, K.; Wang, Z.; and Zhang, X. 2025. ProSec: Fortifying Code LLMs with Proactive Se- curity Alignment. In International Conference on Machine Learning (ICML). ArXiv:2411.12882. Yang, J.; Lieret, K.; Jimenez, C. E.; Wettig, A.; Khandpur, K.; Zhang, Y.; Hui, B.; Press, O.; Schmidt, L.; and Yang, D. 2025. SWE-smith: Scaling Data for Software Engineering Agents. In Advances in Neural Information Processing Sys- tems (NeurIPS), Datasets and Benchmarks Track. Spotlight. arXiv:2504.21798. Zhang, A. K.; et al. 2025. BountyBench: Dollar Impact of AI Agent Attackers and Defenders on Real-World Cyber- security Systems. In Advances in Neural Information Pro- cessing Systems (NeurIPS), Datasets and Benchmarks Track. ArXiv:2505.15216. Zhu, Y.; et al. 2025. CVE-Bench: A Benchmark for AI Agentsâ Ability to Exploit Real-World Web Application Vul- nerabilities. In International Conference on Machine Learn- ing (ICML). Spotlight. arXiv:2503.17332. Zhuo, T. Y.; Ding, Y.; Guo, W.; and Meng, R. 2026. To Defend Against Cyber Attacks, We Must Teach AI Agents to Hack. arXiv preprint arXiv:2602.02595. Zhuo, T. Y.; Wang, D.; Ding, H.; Kumar, V.; and Wang, Z. 2025a. Cyber-Zero: Training Cybersecurity Agents without Runtime. arXiv preprint arXiv:2508.00910. Zhuo, T. Y.; Wang, D.; Ding, H.; Kumar, V.; and Wang, Z. 2025b. Training Language Model Agents to Find Vulnera- bilities with CTF-Dojo. arXiv preprint arXiv:2508.18370. A The CyberForge Corpus This section describes the released corpus. An instance is one injected weakness together with the proof of vulnerabil- ity that triggers it, admitted only after the differential oracle accepted the pair. Table 4 provides an overview of our gen- erated corpus. Table 4: The CyberForge corpus at a glance. Corpus Validated instances1 034 Pipeline 1 (fuzzer-guided)643 Pipeline 2 (agentic)391 OSS-Fuzz projects qualified100 contributing⼠1 instance80 Distinct weakness categories (CWE)63 Distinct CWE groups25 By languageProjects Instances C++73697 C27337 A.1 Projects CyberForge targets C and C++ projects from OSS-Fuzz. A project enters the pool only if its own test suite builds, runs unattended and passes at a 100 % rate on unmodified code. This left 100 qualified projects, 80 of which contributed at least one validated instance. Table 5 lists them. A.2 Weakness Coverage The corpus covers 63 CWE types across 25 classes. Table 7 enumerates every CWE type and Figure 7(a) shows the most frequently injected. Memory-safety weaknesses dominate, as they do among real C/C++ disclosures. The two injection pipelines cover different CWE types, so running both increases coverage and diversity. The fuzzer- guided pipeline covers 15 CWE types and relies on the paths recorded by existing libFuzzer harnesses, which favor mem- ory safety weaknesses. The agentic pipeline covers 62 dis- tinct CWE types. It selects sites using static analysis and retrieval, which allow for more freedom regarding the types of vulnerability it can inject. The pipelinesâ coverage overlap on 14 CWE types. 46 projects received instances from both pipelines, 7 from the fuzzer-guided pipeline alone, and 27 solely from the agentic pipeline. Table 6: Weakness categories realized in the corpus, grouped by the coarse family the injection pipeline selects over. Groups are ordered by instance count and identifiers within a group by their own instance count. GroupCWE identifiers realized Post buffer operation CWE-125, CWE-120, CWE-130, CWE-129, CWE-122, CWE-119, CWE-787, CWE-121, CWE-170, CWE-126, CWE-680, CWE-823 CalculationCWE-193, CWE-131, CWE-369 Invalid pointerCWE-476, CWE-824 WebCWE-20 Expired memoryCWE-416, CWE-415 Numeric errorsCWE-190, CWE-191, CWE-189, CWE-197, CWE-682 Resource management CWE-404, CWE-400, CWE-399, CWE-666, CWE-770 Unhandled errorsCWE-703, CWE-391, CWE-754 Return valueCWE-252, CWE-690 Input validationCWE-78, CWE-74, CWE-77, CWE-95 Memory leakCWE-401 OtherCWE-863, CWE-203, CWE-354, CWE-532 Access controlCWE-264, CWE-284 ConfidentialityCWE-200, CWE-209 Path-relatedCWE-22 ConcurrencyCWE-362 Memory releaseCWE-590, CWE-762 PrivilegesCWE-269, CWE-271 InitializationCWE-457 Loop and recursionCWE-674 StringsCWE-134 APICWE-475 Control flowCWE-670 EncapsulationCWE-485 Function callCWE-227 (none recorded)CWE-617, CWE-665 A.3 Generated Instance Characteristics Table 8 reports the size of the artifacts that make up a weak- ness instance. Injected edits are small and local, which helps them stay latent: 1 025 of 1 034 instances changed a single file, 944 confined the change to one hunk, that is one con- tiguous block of changed lines with its surrounding context. Every instance ships a PoV script to trigger the vulnerabil- ity, which implementation differs depending on the pipeline (Table 9). The fuzzer-guided pipeline replays an input recov- ered from a seeded libFuzzer session. The agentic pipeline ships a fixed input file the agent constructed, along with a driving program. Table 5: All 100 qualified OSS-Fuzz projects. L: primary language. Type: application domain. Stars: GitHub stars where applicable. Files and KLoC: C/C++ source files and thousands of lines in the projectâs own tree, measured over compiled sources. P1/P2: instances from the fuzzer-guided and agentic pipelines. CWE: distinct weakness categories present. UT: tests in the projectâs own suite. ProjectL TypeStars Files KLoC P1 P2 CWE UT arrowC++ Data16 96864 0 96 11 assimpC++ Media 13 101 636 300 12 109 584 behaviortreecpp C++ Utility 4 135 134 373 0 33 13 binutilsC++ Systemâ 1 603 2 013 0 00 222 bluezC Network 1 120 455 316 7 47 37 brotliC++ Compr. 14 820 11143 29 10 11 73 c-bloscC++ Compr. 1 056 14392 6 76 1 643 c-blosc2C++ Compr.581 431 140 0 125 2 017 cgifC Media150737 7 56 60 cjsonC++ Data12 8902811 7 23 15 19 coturnC Network 14 2615126 5 16 13 16 cryptofuzzC++ Crypto26 228 135 0 005 dnsmasqC Networkâ1110 0 65 48 double-conversion C++ Numeric 1 19339 329 34 559 envoyC++ Network 28 669 893 184 0 008 espeak-ngC++ Text6 696 11257 8 87 19 exiv2C++ Media1 145 201 107 3 356 ffmpegC++ Media 62 591 1 057 337 0 00 2 779 fileC++ Utility 1 6393722 1 01 86 flacC++ Media2 371 15670 4 46 26 flexC Runtime 4 0363531 0 33 203 fluent-bitC++ Network 8 001 2 198 1 344 6 13 63 fmtC++ Utility 23 6966870 29 11 12 21 freerdpC Network 13 508 1 462 534 0 33 155 ghostscriptC++ Docâ 2 078 2 086 0 116 grokC++ Media290 967 437 0 74 177 guetzliC++ Media 12 9174810 33 138 10 h2oC++ Network 11 521 355 164 0 64 37 h3C Numeric 6 432 17436 67 17 14 315 haproxyC++ Network 6 742 467 303 0 334 harfbuzzC++ Text5 957 399 166 27 58 66 hdf5C Data962 1 279 1 140 5 02 2 804 htslibC++ Data939 159 117 8 25 353 hunspellC++ Text2 5505690 4 125 139 icuC++ Text3 563 1 134 589 6 36 21 jqC Data35 3085739 20 13 119 json-cC++ Data3 286 13717 9 59 26 jsoncppC++ Data8 8773014 0 22 124 jsonnetC++ Runtime 7 549 104 124 0 22 59 kamailioC Network 2 891 420 185 20 38 45 kimageformatsC++ Mediaâ8741 0 00 45 lcmsC++ Media7303544 17 15 148 leptonicaC++ Media2 068 568 324 2 87 121 libarchiveC++ Compr. 3 572 995 243 0 64 897 libdwarfC System256 284 148 0 33 22 libjxlC++ Media3 610 590 196 10 97 13 liblouisC Text3388153 0 00 18 libpngC++ Media1 6363642 22 26 36 libredwgC Data1 513 446 990 0 00 254 libsassC++ Runtime 4 325 14840 9 17 13 27 ProjectL TypeStars Files KLoC P1 P2 CWE UT libsndfile C Media 1 705 13365 2 02 143 libsrtpC++ Crypto 1 3946930 14 26 11 libuclC Data1 7392219 2 768 libvipsC++ Media 11 540 464 258 0 227 libxsltC++ Docâ6351 0 11 10 libyangC Data426 332 213 5 24 61 libzipC++ Compr. 1 033 21723 18 39 183 lighttpdC Network 702 169 100 0 22 232 llvmC++ Runtime 39 572 1 948 805 0 00 10 mbedtlsC++ Crypto 6 845 566 649 2 01 133 mrubyC++ Runtime 5 597 266 180 3 67 1 773 njsC++ Runtime 1 588 12194 4 34 6 024 ntopngC++ Network 8 047 12457 0 00 17 open5gsC Network 2 657 7 526 1 475 10 153 open62541C++ Network 3 192 199 130 0 44 15 opencvC++ Media 90 2378844 5 24 135 openh264C++ Media 6 125 21783 1 55 631 openjphC++ Media2917641 0 33 82 openscC++ Crypto 3 061 301 216 0 225 opensslC Crypto 30 536 1 702 606 9 36 26 openthread C++ Network 3 999 1 089 560 0 339 openvpnC Network 14 321 18193 0 00 17 pcapplusplus C++ Network 3 121 329 144 0 44 304 pcre2C++ Utility 1 32962 109 12 044 perfettoC++ Systemâ 9 12 649 phpC++ Runtime 40 267 1 096 1 377 0 00 816 popplerC++ Docâ 373 194 0 00 15 protobuf-c C Data2 9853971 17 16 11 pupnpC Network 437 14056 20 46 14 qemuC Systemâ 4 007 1 483 0 00 213 qpid-proton C++ Network 249 10537 0 00 29 quickjsC Runtime 10 8892380 28 13 168 radare2C++ System 24 462 1 180 643 0 21 575 relicC++ Crypto513 386 166 0 11 19 rubyC++ Runtime 23 666 358 187 0 00 894 selinuxC System 1 612 275 110 4 35 68 serenityC++ System 33 70672 26 247 simdjsonC++ Data24 10272 17 15 118 skiaC++ Mediaâ 619 165 0 008 systemdC++ System 16 540 2 452 827 7 36 15 unboundC Network 4 750 215 188 0 00 88 unicornC++ System 9 201 516 451 4 02 11 uwebsockets C++ Network 18 9375716 0 117 wamrC Runtime 6 043 130 117 0 00 148 wiresharkC++ Networkâ 2 966 5 746 0 1389 wuffsC++ Media 4 7951495 1 22 78 xzC++ Compr. 1 624 14839 0 63 19 yajl-rubyC++ Data1 489153 0 00 416 zeekC++ Network 7 830 2 542 1 156 0 00 113 zlib-ngC++ Compr. 2 056 17762 6 02 70 Table 7: All 63 weakness categories realized in the corpus, ordered by instance count. Names follow MITRE. P1/P2: instances per pipeline, with the Pipeline 2 count split by selection strategy into E (agentic exploration) and R (retrieval). Pr.: projects in which the category occurs. CWENameAll P1 P2 E R Pr. CWE-125 Out-of-bounds Read194 146 48 14 34 46 CWE-193 Off-by-one Error147 145 2 1 1 38 CWE-476 NULL Pointer Dereference134 115 19 7 12 41 CWE-120 Buffer Copy without Checking Size of Input (âClassic Buffer Overflowâ)111 105 6 3 3 35 CWE-130 Improper Handling of Length Parameter Inconsistency60 60 0 0 0 10 CWE-129 Improper Validation of Array Index55 50 5 5 0 22 CWE-20 Improper Input Validation52 0 52 48 4 24 CWE-122 Heap-based Buffer Overflow39 11 28 12 16 22 CWE-119 Improper Restriction of Operations within the Bounds of a Memory Buffer37 0 37 13 24 24 CWE-416 Use After Free25 1 24 6 18 18 CWE-787 Out-of-bounds Write21 0 21 3 18 16 CWE-121 Stack-based Buffer Overflow12 3 9 4 5 9 CWE-190 Integer Overflow or Wraparound12 1 11 4 7 9 CWE-703 Improper Check or Handling of Exceptional Conditions11 0 11 0 11 8 CWE-252 Unchecked Return Value10 0 10 10 0 6 CWE-404 Improper Resource Shutdown or Release10 0 10 10 0 2 CWE-415 Double Free10 1 9 5 4 7 CWE-131 Incorrect Calculation of Buffer Size5 0 5 5 0 4 CWE-401 Improper Release of Memory Before Removing Last Reference (âMemory Leakâ)5 2 3 1 2 5 CWE-191 Integer Underflow (Wrap or Wraparound)4 0 4 1 3 3 CWE-22 Improper Limitation of a Pathname to a Restricted Directory (âPath Traversalâ)4 0 4 2 2 4 CWE-400 Uncontrolled Resource Consumption (âResource Exhaustionâ)4 0 4 3 1 3 CWE-690 Unchecked Return Value to NULL Pointer Dereference4 0 4 4 0 4 CWE-189 Numeric Errors3 0 3 0 3 3 CWE-200 Information Exposure3 0 3 1 2 3 CWE-362 Concurrent Execution using Shared Resource with Improper Synchronization3 0 3 0 3 2 CWE-369 Divide By Zero3 1 2 1 1 3 CWE-399 Resource Management Errors3 0 3 0 3 3 CWE-78 Improper Neutralization of Special Elements used in an OS Command3 0 3 3 0 3 CWE-134 Uncontrolled Format String2 0 2 0 2 2 CWE-170 Improper Null Termination2 0 2 2 0 2 CWE-197 Numeric Truncation Error2 0 2 2 0 2 CWE-264 Permissions, Privileges, and Access Controls2 0 2 0 2 1 CWE-269 Improper Privilege Management2 0 2 0 2 2 CWE-284 Improper Access Control2 0 2 2 0 2 CWE-391 Unchecked Error Condition2 0 2 2 0 1 CWE-457 Use of Uninitialized Variable2 0 2 1 1 1 CWE-590 Free of Memory not on the Heap2 1 1 1 0 2 CWE-617 Reachable Assertion2 0 2 2 0 2 CWE-666 Operation on Resource in Wrong Phase of Lifetime2 0 2 2 0 1 CWE-674 Uncontrolled Recursion2 1 1 1 0 2 CWE-754 Improper Check for Unusual or Exceptional Conditions2 0 2 0 2 1 CWE-770 Allocation of Resources Without Limits or Throttling2 0 2 2 0 2 CWE-824 Access of Uninitialized Pointer2 0 2 1 1 2 CWE-863 Incorrect Authorization2 0 2 0 2 2 CWE-126 Buffer Over-read1 0 1 1 0 1 CWE-203 Observable Discrepancy1 0 1 0 1 1 CWE-209 Information Exposure Through an Error Message1 0 1 1 0 1 CWE-227 Improper Fulfillment of API Contract (âAPI Abuseâ)1 0 1 1 0 1 CWE-271 Privilege Dropping / Lowering Errors1 0 1 1 0 1 CWE-354 Improper Validation of Integrity Check Value1 0 1 0 1 1 CWE-475 Undefined Behavior for Input to API1 0 1 1 0 1 CWE-485 Insufficient Encapsulation1 0 1 1 0 1 CWE-532 Insertion of Sensitive Information into Log File1 0 1 0 1 1 CWE-665 Improper Initialization1 0 1 1 0 1 CWE-670 Always-Incorrect Control Flow Implementation1 0 1 0 1 1 CWE-680 Integer Overflow to Buffer Overflow1 0 1 1 0 1 CWE-682 Incorrect Calculation1 0 1 0 1 1 CWE-74 Improper Neutralization of Special Elements in Output Used by a Downstream Component (âInjectionâ)1 0 1 1 0 1 CWE-762 Mismatched Memory Management Routines1 0 1 1 0 1 CWE-77 Improper Neutralization of Special Elements used in a Command1 0 1 1 0 1 CWE-823 Use of Out-of-range Pointer Offset1 0 1 1 0 1 CWE-95 Improper Neutralization of Directives in Dynamically Evaluated Code (âEval Injectionâ)1 0 1 1 0 1 050100150200 instances CWE-400 CWE-131 CWE-401 CWE-252 CWE-404 CWE-415 CWE-703 CWE-121 CWE-190 CWE-787 CWE-416 CWE-119 CWE-122 CWE-20 CWE-129 CWE-130 CWE-120 CWE-476 CWE-193 CWE-125 4 5 5 10 10 10 11 12 12 21 25 37 39 52 55 60 111 134 147 194 (a) Pipeline 1 Pipeline 2 050100150200250300350 instances SEGV SIGSEGV calloc-overflow allocation-size-too-big fuzz-target-exited stack-buffer-underflow memcpy-param-overlap FPE stack-overflow container-overflow assertion-failure out-of-memory invalid-free/alloc-mismatch heap-use-after-free global-buffer-overflow memory-leak deadly-signal stack-buffer-overflow SEGV heap-buffer-overflow 1 2 2 2 3 3 4 5 5 5 8 9 15 25 29 38 60 86 138 332 (b) Figure 7: What the corpus covers, by pipeline. (a) The 20 most frequent CWE identifiers; Table 7 gives their names. (b) The 20 most frequent runtime fault classes in the sanitizer reports. Table 8: Size of the artifacts that make up an instance. Micro- averages over all instances, not grouped by project; the final row is per project. Med. Mean p90 Max Injected diff Lines added11.19217 Lines deleted12.794 643 Lines changed23.985 644 Hunks11.521 337 Files11.0113 Verification artifacts PoV entry script (lines)20 22.69 49 185 Project test suite (tests)41 281.60 633 6 024 Table 9: Form of the released proof of vulnerability. Lines: mean length of the exploit.sh entry point. PoV formAll P1 P2 Lines fuzz-discovered replay 421 42104 script-constructed input 341 222 11936 fixed input file2720 27235 A.4 Resemblance to Real Vulnerabilities The main paper reports a KolmogorovâSmirnov distance of 0.165 between the injected vulnerabilities and real ones, compared with a real-to-real baseline of 0.190. This section describes how those values were obtained. For an edit statistic, let x 1 ,...,x n denote the observa- tions from the injected corpus and y 1 ,...,y m those from a reference corpus of real vulnerabilities. If F n and G m are their empirical distribution functions, the two-sample KolmogorovâSmirnov statistic is D n,m = sup x F n (x)â G m (x) , It measures the largest gap between the two empirical distri- butions. A value of 0 means that the observed distributions coincide, while larger values indicate greater separation. The statistic requires no parametric model, which is useful be- cause patch-size distributions are strongly skewed. The reference corpus contains all 300 SEC-bench real- world instances: 200 from the cve split and 100 from the oss split. We compute the statistic along five axes: func- tions changed, files changed, hunks, changed lines, and added lines. The first three capture the structure of an edit; the last two capture its size. A KS distance has no universal threshold for similarity. We therefore compare the SEC-benchoss andcve splits against each other. Since both contain real vulnerability patches, but still come from two separate data sources, their distance provides a practical baseline for the variation between two real corpora. An injected-to-real distance near or below this baseline is therefore not, by itself, evidence that the injected edits are distinguishable as artificial. For functions modified, the injected corpus has a distance of 0.165, below the real-to-real baseline of 0.190. The corre- sponding distances for files touched and hunk count are 0.123 and 0.243, compared with baselines of 0.065 and 0.205. Thus, the injected edits broadly resemble real patches in where and how they are distributed across the codebase. B Injection Pipelines Both pipelines start from a selected candidate location and terminate at the same differential oracle. The fuzzer-guided pipeline (Figure 8) considers only func- tions reachable from an existing libFuzzer harness and ranks them by triggerability. The model performs a single-shot edit, after which the harness fuzzes the modified project for 90 s using a seeded corpus. A failed candidate is retried once before the pipeline moves on. The agentic pipeline (Figure 9) iteratively injects a weak- Vulnerability Generation Exploit Validation Stage 1: Input Stage 2: InjectionStage 3: Post-hoc FuzzingStage 4: Verifier Scored Location Fuzzer harness Target function Triggerability Bug shape (CWE) fuzzer function scoring LLM Injection Vulnerability Injection Vuln. patch single-shot editdiff, builds Post-hoc Fuzzing libFuzzer run 90 s, value profile builtin + curated corpus, replay rediscover a crashing input (PoV) Crash found? Verified? Yes No Yes No Differential Verifier â Crashes on vulnerable â Clean on original â Unit tests pass replay PoC on vulnerable vs. original build Vuln. Snapshot fail: retry the candidate once, else move to the next Input InjectionFuzzing Differential Verification Figure 8: P1: CyberForgeâs fuzzer-guided injection pipeline. Vulnerability Generation Exploit Validation Stage 1: Input Stage 2: InjectionStage 3: ReachabilityStage 4: ExploitStage 5: Verifier Selected Location Selected CWE Call chain Dataflow Reachability tier from LLM or retrieval Iterative Injection Vulnerability Injection Generated vuln. Compile & unit tests edit the sink, compile, run tests Taint Analysis sink reachable from entry point CodeQL call chain Sink reached? Verified? YesYes No No < 5 No < 3 PoV Generation PoV oracle ASan, LSan, UBSan, crash side effect, output diff one oracle per weakness Differential Verifier â Triggers on vulnerable â Clean on original â Unit tests pass exploit on vulnerable vs. original build Vuln. Snapshot on failure, re-inject at the same site Input InjectionReachability ExploitDifferential Verification Figure 9: P2: CyberForgeâs agentic in-context injection pipeline. ness at a selected location, using compiler and unit-test feed- back. Once the project builds and its tests pass, a taint- analysis agent examines CodeQL-extracted dataflow from the source (an entry point through which external input en- ters the program) to the sink (a code location where that input is used in a potentially unsafe operation). The agent au- tonomously explores the dataflow graph backward from the sink, iteratively identifies inputs that could trigger the vul- nerable behavior, and verifies that an external-input source can still reach the injected sink. If no such path exists, the analysis context is returned to the injection agent as feedback. Otherwise, a proof-of-vulnerability (PoV) agent constructs a trigger using strategies tailored to the weakness type. Both pipelines use Gemma 4 31B through mini-swe-agent. No sampling parameters are overridden, so generation uses the model defaults: temperature 1.0, top-p 0.95, and top-k 64. Each agent invocation is capped at 200 iterations. C Generation Cost This section reports the cost of generating the CyberForge corpus and collecting the teacher trajectories. We account for self-hosted inference in two ways: the elec- tricity consumed during generation and the estimated cost of processing the same number of tokens through a hosted API. For API-based inference, we report the charges recorded by the provider. The accounting assumes 2ĂH100 SXM at 700 W, CPU nodes at 400 W, a PUE of 1.3, and average electricity cost at $0.1359/kWh. Hosted inference for a Gemma-class model is priced at OpenRouterâs published rate of $0.09 per million in- put tokens and $0.34 per million output tokens (2026-07-31). During our experiment GPT-5.4-mini was billed at $0.0375 per million cached input tokens and $2.25 per million output tokens. GPU time covers model inference. CPU time covers the per-project Docker containers used to build each target, run the fuzzing harnesses, and execute the unit tests. Container execution incurs no token cost, but its energy use is included in the metered electricity estimate. By contrast, the API- equivalent estimate prices model tokens only and excludes all container work, so it does not capture the full cost of running the pipeline on hosted infrastructure. Table 10 reports the GPU and CPU time used for vulner- ability injection and teacher-trajectory generation. Table 11 reports token usage at each stage of the two pipelines. Table 12 summarizes the estimated cost of CyberForge. Corpus generation consumed $253 in electricity; pricing the same token volume at hosted-inference rates, while retain- ing the cost of running the containers, raises the estimate to 010203040 0 50 100 150 200 250 Îź=11.6m, 43.3¢ Teacher: GPT-5.4-mini 020406080 0 100 200 300 Îź=16.0m, 2.2¢ Teacher: Gemma 4 31B 02550751001250246 Cost (cents) Duration (min) Figure 10: Time and cost per teacher trajectory generation run. Duration is read on the lower axis, cost on the upper one. Boxes give the means; axes are clipped at the 99th percentile. 0255075 0 50 100 150 200 250 Îź=19.34m, 4.72¢ Injection agent 02040 0 50 100 150 200 250 Îź=11.20m, CPU only Build and tests 0.00.20.4 0 100 200 300 Îź=0.10m, CPU only Fuzz replay 0.000.250.500.75 0 200 400 600 800 1000 Îź=0.11m, CPU only Differential check 0510 GPU electricity cost (cents) Duration (min) Figure 11: Time and cost breakdown of the P1 fuzzer-guided injection pipeline per attempt. The injection agent is the only stage that calls the model; the rest run on CPU. 020406080 0 200 400 600 Îź=17.5m, 1.77¢ Injection agent 0204060 0 200 400 600 800 Îź=11.5m, CPU only Unit-test suite 0.02.55.07.510.012.5 0 100 200 300 400 500 Îź=2.1m, 0.47¢ Taint/path analysis 020406080 0 100 200 300 Îź=16.1m, 1.80¢ PoV agent 050100150 0 100 200 300 400 500 Îź=35.1m, 3.23¢ Agentic attempt 02460.00.20.40.60.81.0 01230246 GPU electricity cost (cents) Duration (min) Figure 12: Time and cost per sub-agent of the P2 agentic injection pipeline per attempt. Table 10: Compute used for corpus generation and teacher- trajectory collection. CPU hours are machine-hours over the union of active intervals, so concurrent runs count once. The 2ĂH100 endpoint was shared across activities, so GPU wall time is not exclusive to one row. HoursElectricity ActivityCPU GPU CPU GPU Parallelism Injection874 775 $62 $192 4.7â13.0Ă Teacher: Gemma 4 31B9797$7 $246.3Ă Teacher: GPT-5.4-mini 129â$9â2.7Ă Table 11: Token usage for each type of task and phase. Activity / phaseInputOutput Corpus generation P1 injection agent958.8 M 15.47 M P1 fuzz replayno model stage P2 injection agent 1 668.2 M 30.84 M P2 PoV generation819.3 M 19.55 M P2 taint analysis286.7 M5.58 M P2 other agents116.1 M2.00 M Teacher trajectory collection GPT-5.4-mini2 871.7 M 143.23 M Gemma 4 31B526.1 M4.07 M Total7 246.8 M 220.74 M $433. Collecting the teacher trajectories cost $748, includ- ing $738.62 in measured API charges for GPT-5.4-mini and Gemma teacher runs consumed $31 in electricity. The total cost of generating the dataset and collecting teacher trajec- tories was $1 032, compared with an estimated $1 237 if all inference tokens had been purchased through hosted services. Amortized over the validated corpus, generation cost $0.25 per instance in electricity, or $0.42 when inference is valued at hosted rates. The corresponding fully API-billed costs are $0.87 per instance for SEC-bench and $2.77 for CVE-Genie. Figure 10 gives the distributions for teacher trajectories, which take 9 to 11 minutes at the median. Figure 11 breaks the fuzzer-guided attempt down by stage, where the injection agent and the build-and-test gate dominate and the replay and differential checks take about five seconds each, and Figure 12 the agentic attempt by sub-agent, with a median of 27 minutes. Both exclude the 9.6 % of model calls that returned an error before producing any output. D Supervised Fine-Tuning Details We fine-tune Gemma 4 at three scales (E4B, 12B and 31B) on the teacher trajectories collected over the corpus, training one student per base model and teacher. All students use the same LoRA recipe: the base weights stay frozen and low-rank adapters are attached to the attention and MLP projections of the language model only, leaving the vision tower untouched. Table 13 lists the hyperparameters. Teacher-trajectory cleansing. Raw teacher trajectories are recorded in the teacherâs own generation environment and Table 12: CyberForge cost estimation for each task type in- cluding CPU electricity cost. Actual: paid electricity price (or token-cost for GPT-5.4-mini). API: token-based cost (es- timated for Corpus generation and Gemma teacher). Per in- stance divides by the 1 034 validated instances. TotalPer instance ActivityActualAPI Actual As API Corpus generation$253 $433 $0.25 $0.42 Teacher: GPT-5.4-mini$748 $748 $0.72 $0.72 Teacher: Gemma 4 31B$31$56 $0.03 $0.05 Total$1 032 $1 237$1.0$1.2 Table 13: Fine-tuning configuration, identical across all six student/teacher combinations. HyperparameterValue Base modelsGemma 4 E4B / 12B / 31B AdaptationLoRA, base frozen LoRA rank r32 LoRA Îą64 LoRA dropout0.05 Adapted modulesattention + MLP projections PrecisionBFloat16 AttentionSDPA Learning rate1e-4 Weight decay0.0 ScheduleCosine Warmup ratio0.03 OptimizerAdamW (fused) Epochs3 Batch size1 Gradient accumulation 2 Gradient clipping1.0 Gradient checkpointing Enabled Hardware1ĂH200 (147 GB) or H100 Seed42 are not directly usable for training a SEC-bench student, so we pass them through a cleansing pipeline before fine-tuning. (i) We retain only oracle-verified successful trajectories. (i) We align the teacher environment to the SEC-bench evalu- ation harness (Lee et al. 2025): repro/build invocations are normalized to secb repro/secb build, exploit-artifact paths are remapped to /testcase, and ripgrep calls are rewritten to grep (the evaluation container lacks the ripgrep package). (i) Each trajectory is linearized to one command per assistant turn. (iv) The teacherâs reasoning is retained, after removing its boilerplate bold-header summary. (v) Tool outputs are re-rendered through the evaluation observation template (a 10 k-character head/tail cap) and long observation histories are compressed with a sliding window (recent observations kept in full, older ones reduced to short stubs) so each tra- jectory fits the training context without ever truncating the assistant turn that writes the patch. In the main paper we show that our fine-tuned models main- tain some gains even in out-of-distribution setting with dif- ferent evaluation environment (keeping the mini-swe-agent scaffold) E Example of Injected Vulnerability This section presents one instance of the generated corpus, guetzli/vulnerability_FZ_24: the weakness Cy- berForge introduced, the input that triggers it and explana- tions about this vulnerability. Guetzli is Googleâs JPEG compressor, used by image hosts, CDNs, and web developers to reduce image file sizes before delivery. E.1 The Vulnerability A JPEG file consists of a series of segments containing either compressed image data or metadata (e.g. color profiles and camera settings). Each segment begins with a two-byte length field that tells the decoder how many bytes belong to it. In ProcessAPP (Listing 1), the original code validates this field in two steps. VERIFY_INPUT checks that the de- clared length is valid under the JPEG format, between 2 and 65535. VERIFY_LEN then checks that the input buffer actually contains that many bytes. CyberForge removed the buffer-length check. As a result, a JPEG may declare a segment length of up to 65535 bytes while providing much less data. The std::string constructor uses the declared length when copying from the segment, causing it to read past the end of the input buffer. This is an out-of-bounds read, CWE-125, because the attacker controls the copy length without having to supply the corresponding number of bytes. E.2 Triggering the Vulnerability The trigger is a 504-byte file that opens with the bytes: F D8 F E0 F F 4A 46 49 46 The file starts normally: F D8 is the JPEG start marker, and F E0 begins an APP0 metadata segment. The next two bytes, F F, declare a segment length of 65 535 bytes. This is the largest value accepted by VERIFY_INPUT. Only 504 bytes are present, so the removed VERIFY_LEN check would have rejected the file. Without it, the code proceeds using the declared length. The std::string constructor then attempts to copy 65 536 bytes from an offset three bytes into the buffer. Since only 501 bytes remain, the read extends 65 035 bytes beyond the end of the file. E.3 Why the Defect Is Realistic This bug follows the same basic pattern as Heartbleed (CVE- 2014-0160): an attacker supplies a length larger than the accompanying data, and the program reads beyond that data into adjacent memory. File formats with embedded length fields are especially prone to this class of error, including image metadata segments. The defect is also easy to miss. The attacker-controlled value is still checked against the JPEG formatâs permitted range shortly before it is used, which can make the code ap- pear adequately validated during review. The missing check concerns whether the declared length fits within the actual input buffer. Listing 1: Example of vulnerability injected by CyberForge in the Guetzli repository. The line in red is the one the injection deletes; nothing else changes. bool ProcessAPP(const uint8_t * data, const size_t len, size_t * pos, JPEGData * jpg) VERIFY_LEN(2); size_t marker_len = ReadUint16(data, pos); VERIFY_INPUT(marker_len, 2, 65535, MARKER_LEN); - VERIFY_LEN(marker_len - 2); // Save the marker type with the app data. std::string app_str( reinterpret_cast<const char * >( &data[ * pos - 3]), marker_len + 1); * pos += marker_len - 2; jpg->app_data.push_back(app_str); return true; Ordinary unit tests are unlikely to catch the problem. JPEGs produced by conforming encoders contain segment lengths that match the available data, so the removed check has no visible effect on valid files. Triggering the bug requires a deliberately malformed JPEG with a valid length value but insufficient segment data. E.4 Impact The out-of-bounds read could disclose server memory. In an unsanitized production build, the copied bytes become part of app_data and are written into the re-encoded JPEG returned to the uploader. Because the segment length is 16 bits, a single request can expose nearly 64,KB beyond the input buffer. The leaked region may contain data from other work han- dled by the same process, including image buffers or meta- data belonging to other users. Depending on the heap lay- out, it could also contain session tokens, API keys, or other secrets. Repeated uploads may reveal different regions as allocations change. The request need not look like a failure. The service can accept the upload, return a valid JPEG, and record the oper- ation as successful while unintentionally including process memory in the response. E.5 Directory Structure and File Contents Every instance ships as a self-contained directory with the following layout. The files that define this instance are repro- duced below. guetzli/ |-- project.json # language , upstream URL , secure base commit |-- setup/ # OSS-Fuzz build | |-- Dockerfile | |-- build.sh |`-- project.yaml |-- unit_tests/ # non-regression gate | |-- test.sh # standardized entrypoint |`-- parse_results.py # -> "passed": N, "failed": M `-- vulnerabilities/ |-- vulnerability_FZ_0/ # one directory per instance | ... `-- vulnerability_FZ_24/ # the instance detailed below |-- inject_vulnerability.diff # apply -> introduces the vulnerability |-- vulnerability_metadata.json # id , cwe_id , secure base commit |-- sanitizer_report.txt # sanitizer crash proving it triggers `-- exploit_files/ |-- exploit.sh # proof-of-vulnerability entrypoint |-- fuzz_poc.py # PoV driver `-- generated_inputs/ # seed corpus project.json "project": "guetzli", "main_repo_url": "https :// github.com/google/guetzli", "target_dir": "guetzli", "secure_base_commit": "214 f2b42abf5a577c079d00add5d6c470620d3", "unit_tests": "enabled": true , "expected_passing_count": 10, "language": "c++" inject_vulnerability.diff diff --git a/guetzli/jpeg_data_reader.c b/guetzli/jpeg_data_reader.c @@ -398,7 +398 ,7 @@ bool ProcessAPP(const uint8_t * data , size_t * pos , ...) VERIFY_LEN (2); size_t marker_len = ReadUint16(data , pos); VERIFY_INPUT(marker_len , 2, 65535 , MARKER_LEN); - VERIFY_LEN(marker_len - 2); + // Save the marker type together with the app data. std:: string app_str(reinterpret_cast <const char * >( &data[ * pos - 3]), marker_len + 1); vulnerability_metadata.json "id": "vulnerability_FZ_24", "project": "guetzli", "producer": "fuzz_poc_guided", "cwe_id": "CWE-125", "cwe_group": "Post buffer operation", "secure_base_commit": "214 f2b42abf5a577c079d00add5d6c470620d3" exploit_files/exploit.sh #!/ bin/bash set -euo pipefail cd /src/guetzli python3 exploit_files/fuzz_poc.py exploit_files/fuzz_poc.py (excerpt) fuzzer = CFG["selected_fuzzer"]["fuzzer"] binary = Path("/out") / fuzzer # the built OSS-Fuzz target ... def run_and_capture(args , log_name): proc = subprocess.run(args , stdout=subprocess.PIPE , stderr=subprocess.STDOUT , text=True) output = proc.stdout crash = ("AddressSanitizer" in output or "UndefinedBehaviorSanitizer" in output or "runtime error:" in output) return proc , crash , ... ... # time-boxed libFuzzer campaign over the seed corpus args = [str(binary), f"-max_total_time =CFG.get('max_total_time', 60)", f"-max_len = max_len", f"-dict= dict_path", str(CORPUS_DIR)] proc = subprocess.run(args , stdout=subprocess.PIPE , stderr=subprocess.STDOUT , text=True) ... asan_like = ("AddressSanitizer" in proc.stdout or "runtime error:" in proc.stdout) crash = bool(crash_artifacts) or (asan_like and not oom and not leak) print("TRIGGERED" if crash else "NOT_TRIGGERED") exploit_files/generated_inputs/ - triggering input (504 bytes, hexdump) 00000000 f d8 f e0 f f 4a 46 49 46 00 01 01 02 00 1c ...... JFIF ...... 00000010 00 1c 00 00 f db 00 43 00 28 1c 1e 23 1e 19 28 .......C.(..#..( 00000020 23 21 23 2d 2b 28 30 3c 64 41 3c 37 37 3c 7b 58 #!#-+(0<dA <77<X ... # 504 bytes total. Bytes 0-1 = SOI (f d8); bytes 2-3 begin an APP0 # segment whose length field (bytes 4-5) is f f = 65535 , far more # than the 504 bytes present -> ProcessAPP reads past the input buffer. sanitizer_report.txt (excerpt) ==432== ERROR: AddressSanitizer: heap-buffer-overflow READ of size 65531 at 0x6fc93620b1f8 thread T0 #0 ProcessAPP jpeg_data_reader.c :403:15 SUMMARY: AddressSanitizer: heap-buffer-overflow jpeg_data_reader.c :403:15 in guetzli :: ProcessAPP