Skip to content

Back to the catalog

Bullying LLMs
blog.zsec.ukwriteup

Bullying LLMs

A researcher details an autonomous vulnerability-hunting system built with Claude Code and 8 custom MCP servers (300+ tools) across a 5-VM Proxmox lab, using a "hallucination bin" validation pipeline (findings must pass PoC/exploitability/low-priv gates before promotion) and a RAG-backed knowledge loop that learns from prior campaigns. Concrete outputs include two new Go standard library CVEs (CVE-2026-33809 TIFF OOM, CVE-2026-33812 SFNT/GPOS OOM), a four-stage Windows OEM management-agent chain (named-pipe auth bypass → SSRF via WCF → catalog injection → SYSTEM code execution via BYOVD), and two macOS app-distributor findings (browser/quarantine DB exfiltration and a leaked debug RSA key enabling Sparkle update-signature bypass). Also covers a self-built token-cost/ROI tracker (TokenBurn) and a bounty-program ROI-scoring model for target selection.

TL;DR Deep dive into an autonomous Claude Code + MCP fuzzing/RE lab that produced 2 Go stdlib CVEs and a Windows SYSTEM 0-day via a "hallucination bin" validation pipeline.
Document

What it is

Two OOM CVEs in golang.org/x/image, each reproducible from a tiny crafted input, plus the concrete validation-gate design and ROI math behind the autonomous hunter that found them. The summary names the CVEs; it does not carry the payloads, version boundaries, or fix commits that let an engineer decide whether their own image/font-parsing code is exposed.

How it works

CVE-2026-33809 (x/image/tiff) — an 8-byte file OOMs any Go process decoding TIFF via the io.Reader (non-ReaderAt) path:

\x49\x49\x2a\x00\xff\xff\xff\xff

Valid little-endian TIFF header, magic 0x002A, followed by an IFD offset of 0xFFFFFFFF. buffer.fill() tries to read to that offset and allocates ~4 GB. The earlier fix for CVE-2022-41727 (safeReadAt) does not cover the IFD offset read at reader.go:477 — a distinct code path. Fixed by chunked reads capped to actual input size: golang/image#25, commit 23ae9ed.

CVE-2026-33812 (x/image/font/sfnt) — in parsePairPosFormat2, numClass1×numClass2 (both uint16 read from the font) is passed unchecked to source.view(). At 65,535 each, product × 2 ≈ 8 GiB. Only the io.ReaderAt path is affected (the []byte path is slice-bounded). Two related weaknesses in the same code: unvalidated indices in makeCachedPairPosGlyph/makeCachedPairPosClass, and missing overflow check in source.varLenView. Fixed by validating against maxTableLength plus bounds/overflow checks: golang/image#26, commit 854c274.

Both came from grammar-based fuzzing (structurally valid files with adversarial field values), not random bytes — across 21 stdlib packages and ~80M executions, only TIFF and SFNT confirmed. WebP/GIF dimension allocations were investigated and ruled working-as-intended by Go maintainers.

Preconditions / Affected

  • TIFF: all golang.org/x/image from v0.0.0 through v0.37.0 (every release); 945+ downstream modules. Requires the io.Reader decode path.
  • SFNT: requires the io.ReaderAt decode path.
  • Impact is DoS (process OOM-kill) on anything parsing untrusted images or fonts: web servers, chat platforms, CI pipelines.

What to do

Update golang.org/x/image past the merged fixes. If pinned, check whether your decode path matches the vulnerable one (io.Reader for TIFF, io.ReaderAt for SFNT) and whether input is attacker-controlled.

Also worth lifting: the validation gates

The system's core discipline — findings start as hallucinations and promote only past four gates — is a reusable pattern, not just this project's plumbing:

  • Gate 0: PoC exists and compiles
  • Gate 1: reproduces in a clean VM snapshot
  • Gate 2: exploitable, not a null deref or graceful exit
  • Gate 3: triggers as a standard user, not SYSTEM/admin

The author's stated lessons: Gate 0 (guilty-until-proven) should be built first — in one session all 6 flagged findings were disproven in dynamic analysis; and Gate 3 caught findings that "looked great from SYSTEM but were unreachable as a normal user." The ROI selection uses conservative minimum-payout estimates against fixed hour costs (DLL hijack ~8h, LPE ~20h, RCE ~40h, UAF/type-confusion ~80h) and a competition multiplier (low 90%, major-OS-vendor 40%, very-high 20%), steering toward under-scrutinised OEM/enterprise software — which is what surfaced the SYSTEM-chain OEM finding.

Caveats

The Windows OEM chain's final BYOVD step relies on a specific WHQL-signed vulnerable driver the author deliberately withholds (no full disclosure), so that stage is not reproducible from the post. The OEM chain and macOS findings are vendor-confirmed but the affected products are unnamed.

Organisations named here

  • AM-PPL

CVEs named here

  • CVE-2026-33809
  • CVE-2026-33812
  • CVE-2017-3528

Technologies named here

  • Claude Code
  • golang.org/x/image
  • Model Context Protocol
  • Windows OEM system management agent
  • macOS application distribution platform
  • FastMCP
  • Ghidra
  • Windows 11
  • ntoskrnl.exe
  • radare2
  • Vendor kernel driver
  • Frida
  • Proxmox
  • FAISS
  • Ollama
  • Sigma rules
  • TokenBurn
  • RAPTOR
  • Go
  • Windows

Techniques named here

  • Grammar-based fuzzing
  • Binary/patch diffing
  • SSRF via WCF method
  • Catalog injection via crafted update package descriptor
  • BYOVD
  • Browser/quarantine database exfiltration
  • Update-signature-key override via preference injection
  • Static analysis + dynamic validation workflow
  • RAG-based prior-finding retrieval before fuzzing