Skip to content

Build1 publisher2 min readPublished

GitHub Security Lab hands fuzz-harness writing and crash triage to an LLM agent

GitHub Security Lab's Fuzzing Taskflow gives an LLM agent one repo slug and has it write harnesses, read coverage and triage crashes for C/C++ projects. The model's build commands run on the host with no container, so the post says to use a disposable machine.

The Engineer · Build desk

Illustration accompanying GitHub Security Lab hands fuzz-harness writing and crash triage to an LLM agent

What happened

  • GitHub Security Lab says projects fuzzed in OSS-Fuzz for years still hide critical bugs because someone must watch coverage, write new harnesses and triage crashes.
  • Its Fuzzing Taskflow takes a GitHub owner/repo slug for a C/C++ project, then has an agent pick entrypoints, write and improve harnesses, run AFL++, triage crashes and report each unique bug.
  • The LLM agent owns the decisions while MCP tools such as run_afl_for and compile_harness do the execution, so the agent never calls AFL or clang itself.
  • Claude Sonnet 5 is the default model because it passed all of the Security Lab's internal tests, and it can be changed in model_config.yaml.

Compiled by The EngineerSomething wrong?How this is made

Why it matters

  • capability The agent can pick its next harness from line and branch coverage produced by replaying AFL's queue, so reading coverage no longer needs a person decoding AFL's edge data.
  • constraint Teams that swap in another model take on the testing the Security Lab did for Sonnet 5, because the post says some frontier models put security guardrails on their outputs.
  • decision A team weighing the agent against hand-written harnesses has to measure it on its own code, and the post's cJSON smoke run is the cheap place to start before a long campaign.

Each harness is compiled twice [12]. The .afl binary is built with afl-clang-lto and -fsanitize=address,undefined, and it is the one AFL++ runs [12]. The .cov binary is built with clang -fprofile-instr-generate -fcoverage-mapping [12]. After the campaign it replays AFL's queue to produce source-line and branch coverage [12]. The post gives the reason: AFL's edge instrumentation is good for guiding the fuzzer and useless for a coverage report a reader can follow [13].

I think the double build is the best engineering in the post. Its premise is that "fuzzing still needs a human in the loop" [2], and it calls the coverage-feedback loop "the heart of the whole pipeline" [14]. That loop automates the step a harness author does by hand: read the report, find the code nobody is reaching, write a harness for it [1].

State handling is just as plain. Everything lives in one SQLite file, fuzz_context.db, and stages pass data to each other only through it, never in memory [11]. After a run, whatever one stage handed the next is sitting on disk to query [11].

The tool boundary in the design is a boundary of responsibility [10]. The same post warns that afl-fuzz, clang and arbitrary build commands chosen by the LLM run directly on the host with no container in between, and that a prompt-injected agent could, in principle, do anything the user can [7]. So the MCP layer is not a sandbox [15]. Credit to the author for putting that warning in the run instructions, where people will actually read it [7]. The post asks for a Codespace or a throwaway VM, used without elevated privileges [7].

The setup and architecture sections of the post do not include bug counts, coverage gains or run costs [16]. The claim that the pipeline works "without a human babysitting it" is the author's description of the design [3]. For that description to hold on another codebase, the agent first has to install AFL, clone the repo, analyze its build system and pick the functions worth targeting, all before AFL++ mutates a single input [3][6].

What to watch

  • Published bug counts or coverage deltas from Fuzzing Taskflow runs on projects already enrolled in OSS-Fuzz.
  • Whether the seclab-taskflows-fuzzing repo adds a container or sandbox around the LLM-chosen build commands.
  • Reports of the pipeline running cleanly on models other than Sonnet 5 through model_config.yaml.
Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories