Configure a Target¶
Use this guide after bin/setup-target or bin/audit --target <target>
has generated output/<target>/target.toml.
Most of the work is review, not hand-authoring. The harness infers a reasonable default config. Your job is to keep the values that are correct and edit only the ones that are unresolved or specific to this target.
What the config has to answer¶
output/<target>/target.toml should answer these questions clearly:
- Where is the ASan executable?
- Are optional sanitizer binaries or suppressions configured for the runners you intend to use?
- Can the harness compile C harnesses for this target?
- Is this a generic target or a browser target?
- What can external input legitimately control?
- How should exported reproduction bundles rebuild or rerun the target?
These answers drive testcase execution at run time and triage at result time. They decide:
- which sanitizer binary to launch;
- which library to link against;
- whether a crash trigger fits the declared attacker surface.
A minimal generic config¶
target = "libxml2"
upstream_url = "https://gitlab.gnome.org/GNOME/libxml2.git"
build_system = "cmake"
pinned_rev = "HEAD"
asan_bin = "build-asan/xmllint"
asan_lib = "build-asan/libxml2.a"
includes = ["include", "build-asan/include"]
link_libs = ["-lz", "-llzma", "-lm"]
is_browser = "0"
[threat_model]
attacker_controls = ["bytes"]
Relative paths resolve under targets/<target>/.
A minimal findings-only config (Python, Ruby, Go, Node, …)¶
For interpreted or managed-runtime targets that have no sanitizer
build, seed an explicit empty [sanitizer].enabled list. Then let the
harness drive testcases through a language-specific [runner] block:
target = "my-py-tool"
upstream_url = "https://example.org/my-py-tool.git"
build_system = "python"
pinned_rev = "HEAD"
is_browser = "0"
[threat_model]
attacker_controls = ["bytes"]
[sanitizer]
enabled = [] # findings-only mode
[runner]
bin = "python3"
args = ["{TESTCASE}"]
env = [
"PYTHONDEVMODE=1",
"PYTHONPATH={TARGET_ROOT}:{TARGET_ROOT}/src:{TARGET_ROOT}/lib",
]
crash_patterns = [] # builtin Python tracebacks are already recognised
The harness runs python3 <testcase> against the interpreter on
PATH. Runtime tracebacks land under findings/ rather than
crashes/. See Auditing non-C/C++ targets for
the full per-language matrix.
Review checklist¶
- Build the default ASan target.
- Refresh the generated config before making local edits:
setup-target refreshes generated fields from the current
checkout and build outputs without touching values you have
already reviewed.
- Confirm
asan_binpoints to the ASan executable you want generic or browser runs to start. - If agents will compile C harnesses, confirm
asan_lib,includes,defines, andlink_libs. You can leave these unresolved if you do not plan to use C harness testcases yet. - Confirm
is_browser = "0"for generic libraries and CLIs, oris_browser = "1"for browser or JS-runtime targets. - Confirm
attacker_controlsmatches the real external input boundary. - If you intend to run UBSan, MSan, or TSan, add those slugs and
binary paths under
[sanitizer]. - Start one bounded session:
Both bin/setup-target and bin/audit validate target.toml
themselves before continuing.
Threat-model choices¶
attacker_controls is read by triage. Keep it conservative.
This field does not decide whether a report is interesting. It
decides whether a crash trigger is reachable through a normal input
boundary for this target. Other concrete security issues can still be
recorded in findings/ even when they are not sanitizer crashes.
| Token | Use when external input controls |
|---|---|
bytes |
File, stream, packet, archive, media, regex, or other input bytes. |
call-sequence |
Ordered public API calls, script calls, plugin calls, or Web API calls. |
timing |
Event-loop scheduling, GC timing, JIT tier-up, or similar timing. |
race |
Thread or process interleaving. |
protocol-state |
Multi-message protocol state. |
env |
Process environment variables. |
fs-state |
Filesystem paths, presence, permissions, or layout. |
A few examples:
# Parser, decoder, archive, codec, regex engine.
[threat_model]
attacker_controls = ["bytes"]
# Browser engine or scriptable runtime.
[threat_model]
attacker_controls = ["bytes", "call-sequence", "timing"]
# Network protocol implementation.
[threat_model]
attacker_controls = ["bytes", "call-sequence", "protocol-state"]
Do not reach for broad controls to make harness-only behaviour look in
scope. If a harness reads an input value and then calls a target API
with an offset or index no real product path would pass, that is
caller-contract misuse — not attacker control. Fix the testcase, or
keep the result outside crashes/. Do not widen the threat model to
push the artifact through triage.
C harness readiness¶
If you expect agents to exercise the target through a small C/C++
harness program (rather than only the CLI binary), the harness
compilation pulls its inputs from target.toml:
- the selected sanitizer's library (
asan_libfor ASan;[sanitizer]entries for UBSan / MSan / TSan); includes;defines;link_libs;- the target source root.
If C harness compilation fails, those are the fields to check.
After repeated C/C++ harness build failures, the audit may make a
conservative additive repair to includes, defines, or link_libs.
It writes a target.toml.bak.<timestamp> backup and logs the action
under the run's logs/ directory.
Harnesses are not limited to C. Sibling
.cc/.cpp/.cxx/.C/.rs/.go/.swift/.kt harnesses compile, and
.py/.rb/.pl/.php/.js/.mjs/.ts/.tsx/.java/.kts/.r/.R/.sh/.bash
harnesses run through their interpreter.
Browser mode readiness¶
For browser targets:
Confirm:
asan_binpoints to the browser executable.- macOS Firefox builds usually use
build-asan/dist/Nightly.app/Contents/MacOS/firefox. - Linux Firefox builds usually use
build-asan/dist/bin/firefox. - Browser ASan runtime dependencies are present.
- JS shell or browser wrappers work for the target.
- Expected controls include
bytes,call-sequence, and only the timing or state dimensions the product actually exposes.
See Browser targets for the longer walkthrough.
Sanitizer policy¶
The harness runs ASan by default. Other supported sanitizer runners
are opt-in per target through the [sanitizer] block in
target.toml. The valid slugs are asan, ubsan, msan, tsan,
and race.
[sanitizer]
enabled = ["asan"]
asan_suppressions = "build-asan/asan-suppressions.txt"
# ubsan_suppressions = "build-ubsan/ubsan-suppressions.txt"
# msan_suppressions = "build-msan/msan-suppressions.txt"
# tsan_suppressions = "build-tsan/tsan-suppressions.txt"
# ubsan_bin = "build-ubsan/xmllint"
# msan_bin = "build-msan/xmllint"
# tsan_bin = "build-tsan/xmllint"
# ubsan_lib = "build-ubsan/libtarget.a"
# msan_lib = "build-msan/libtarget.a"
# tsan_lib = "build-tsan/libtarget.a"
Recommended posture for each:
- ASan — enabled by default. Highest signal, lowest noise.
- MSan — recommended for self-contained libraries (parsers, codecs, archives). Catches uninitialized reads, but every dependency must be MSan-instrumented. That makes it impractical at browser scale.
- UBSan — optional. Useful subset:
vptr,object-size,shift,bounds,signed-integer-overflow. Expect to triage false positives frompointer-overflow,unsigned-integer-overflow, andalignment— mature C/C++ projects often rely on these patterns intentionally. - TSan — optional and demanding. Plan to maintain a suppressions file for the project's threading model. Benign atomics and racy counters fire frequently. Only enable when you can invest in the triage.
- race — Go's runtime race detector. Enable for Go targets built
or run with
-race. Reports containingWARNING: DATA RACEare treated like TSan-class evidence.
See Target config reference for the full field list and per-sanitizer binary overrides.
bin/setup-target <target> --bootstrap builds every sanitizer in
enabled, not just ASan: it converges a per-sanitizer recipe
(.audit/build-<san>.sh), compiles build-<san>/, and fills the
detected <san>_bin / <san>_lib paths. ASan is required; the others
are best-effort and a failed one only warns. The end-to-end walkthrough
is in
Auditing with UBSan, MSan, or TSan.
Even when another sanitizer is enabled, ASan remains the usual first pass for crash prioritisation. It produces the clearest reproduction bundles, and the triage rules are tuned around that workflow.
Reachability scoring fields¶
Add this when it helps:
bin/reachability searches public code for external callers of a
crashing function when scoring severity. This list drops matches from
the project's own sources and known vendored copies so they do not
inflate the caller count.
When the generated values need review¶
Local edits should be small and easy to explain. Common cases:
- the ASan executable has a project-specific name the generator could not infer;
- the useful static library is not the first archive under
build-asan/; - generated headers live outside the default include directories;
- C harnesses need extra system libraries;
- the target exposes controls beyond raw bytes, such as API call sequence or protocol state.
Do not pre-fill fields for features you are not using. A CLI-only
first audit can proceed with a correct asan_bin while C harness
fields are refined later.
Common misconfigurations¶
| Symptom | Likely fix |
|---|---|
bin/audit cannot find target config |
Seed it with bin/audit --target <target> --backend <backend> 1 or bin/setup-target <target>. Confirm --target matches the directory name. |
| Generic testcase runs the wrong binary | Fix asan_bin. Paths are relative to targets/<target>/. |
| C harness compile fails on missing headers | Add source or build include directories to includes. |
| C harness compile fails on missing macros | Add required compiler flags to defines. |
| Link fails during harness compile | Add the ASan library and required system libraries to asan_lib and link_libs. |
| Triage rejects a report as out of scope | Recheck attacker_controls and report Trigger source. Do not widen the model unless the product actually exposes that control. |
For field-by-field details, see Target config reference.