BUG BOUNTYFIELD MANUAL
Reusable module
Markdown
0 / 6 checkedChecks last until this page reloads.

Libraries and parsers: bounded fuzzing to a minimal reproducer

Build a realistic local harness, instrument the target, bound fuzzing resources, and turn unique faults into defensible library or consumer reports.

Investigation sequence
  1. 01Choose contract
  2. 02Build harness
  3. 03Instrument target
  4. 04Fuzz within bounds
  5. 05Minimize root cause
  6. 06Verify consumer impact

At each step: retain the control → record the observation → continue only while the next boundary is understood.

Used in these playbooks#

Choose an attacker-relevant parser contract#

Select a public API and a realistic input boundary: imported image, archive, document, packet, model file, project metadata, or CLI input file. Record who supplies bytes, the consumer's preprocessing, format limits, parser options, and the privilege of the process. Fuzzing an internal helper with impossible arguments may reveal a harness defect rather than a violated library contract.

Keep the first harness narrow: one parse operation, deterministic configuration, fresh state for each input, bounded allocations, and cleanup on both success and failure. Remove network and uncontrolled filesystem side effects. Seed with a few valid, small representative samples to reach deeper code; an all-random corpus may spend every iteration failing the magic-header check.

Harness and build cheat sheet#

The following is a template: product_parser.h, ProductDocument, and the parser functions are placeholders to replace with the target's documented API. Return/error ownership must follow that API. The commands have not been executed here.

#include <cstddef>
#include <cstdint>
#include "product_parser.h"

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
    if (size > 65536) return 0;
    ProductDocument* doc = product_parse(data, size);
    if (doc != nullptr) product_document_free(doc);
    return 0;
}

Build the target library itself with compatible sanitizer and coverage instrumentation; instrumenting only the harness misses much of the parser's behavior. Replace the source list with its reviewed build recipe. The example assumes Clang and a compatible C++ project. AddressSanitizer build guidance.

clang++ -g -O1 -fno-omit-frame-pointer \
  -fsanitize=fuzzer,address,undefined -fno-sanitize-recover=undefined \
  ./fuzz_parser.cc ./parser.cc -o ./fuzz_parser
mkdir -p ./corpus ./artifacts ./evidence
./fuzz_parser ./corpus -max_total_time=120 -timeout=2 \
  -rss_limit_mb=512 -max_len=65536 -artifact_prefix=./artifacts/

Add reviewed seed files before running. libFuzzer's time, input-length, timeout, and RSS settings bound the campaign; they are not a VM resource boundary. Run inside your local disposable environment with external memory/CPU limits appropriate for the workload. Track new coverage and distinct root causes rather than raw executions. libFuzzer reference.

Interpret the failure precisely#

Observation Immediate question Defensible first claim
ASan heap read overflow Does the public API permit this byte sequence? Out-of-bounds read in the tested build
ASan write overflow Which length check and allocation disagree? Out-of-bounds write; execution impact unproven
Use-after-free Did the harness violate ownership rules? Lifetime defect if public usage is valid
UBSan arithmetic finding Does overflow reach an unsafe allocation/index? Undefined operation plus traced consequence
Timeout or RSS limit Is it reproducible at modest input sizes? Bounded evidence of resource exhaustion

-fno-sanitize-recover=undefined makes the selected UBSan failures terminate instead of allowing a fuzzing run to continue after a diagnostic, which helps preserve reproducible failing inputs. UBSan checks selected undefined behaviors, not every arithmetic error. Unsigned integer wrap is defined in C/C++ and is not part of the default undefined group; choose additional checks when the target's threat model requires them. UndefinedBehaviorSanitizer.

Minimize and verify the consumer#

Copy one candidate into ./artifacts/repro.bin, then minimize with a unique output path. Preserve the original input, toolchain, build flags, revision, and symbolized trace.

./fuzz_parser -timeout=2 -rss_limit_mb=512 ./artifacts/repro.bin
./fuzz_parser -minimize_crash=1 -max_total_time=60 -timeout=2 -rss_limit_mb=512 \
  -exact_artifact_path=./artifacts/minimized.bin ./artifacts/repro.bin

Replay the minimized bytes through a supported consumer in the pinned OSS lab. If the consumer rejects them before calling the library, report the library contract separately and leave consumer exposure unproven. A sanitizer crash is not proof of remote code execution, and its absence in an optimized build does not erase a confirmed memory-safety defect.

Hypothetical root cause: a header count is multiplied into a narrow allocation size, then a wider loop trusts the original count. Preserve the values, allocation site, failing access, and missing bound. The fix should bind accepted count to available input and checked allocation size; merely suppressing the crash is insufficient.

  • Public API and ownership contract respected.
  • Target code, not only harness, instrumented.
  • Resources, seeds, revision, and toolchain recorded.
  • Minimal input reproduces the same root cause.
  • Normal input succeeds in affected and fixed builds.
  • Library impact and real consumer exposure are stated separately.

Replay timeout and memory artifacts under the same resource limits as discovery. A minimized crash must retain the original root cause; a shorter input that fails differently is not equivalent evidence.

Vulnerability reverse references#

Nearby shared procedures#

Object, function, and property authorization · Authentication, recovery, federation, and session lifecycle · Trace input into queries, commands, and templates · Server-side fetching and network trust boundaries · Browser execution, cross-origin reads, and forged actions · Uploads, downloads, paths, archives, and XML · Workflow invariants, replay, idempotency, and races · REST, GraphQL, gRPC, WebSocket, and SSE permission parity