Target Config Reference¶
Each target has one reviewed source configuration file:
Create or refresh it with:
bin/audit --target <target> also creates this file when it is missing.
Runtime values such as RESULTS_DIR and TARGET_REV are written separately
to .session-env.
Treat target.toml as generated config plus a small review layer. The
tooling infers:
- source metadata;
- build system;
- browser mode from browser-specific build drivers;
- common ASan executables;
- common static libraries;
- default include paths;
- default sanitizer policy;
- default threat model controls.
Your job is to edit only values that remain unresolved or are wrong for this target.
At audit preflight this file is copied to
output/<target>/<backend>/results/.target.toml. That session snapshot is
immutable. Edit the shared file only for a future run; never change the
snapshot to retarget probes whose evidence is already being recorded.
| Target shape | Minimum execution fields to verify |
|---|---|
| Native CLI | is_browser = "0", enabled sanitizer, matching <san>_bin |
| Native public API | Native CLI fields plus <san>_lib, includes, defines, and link_libs as needed |
| Managed/interpreted runner | [sanitizer] enabled = [] plus [runner].bin and args |
| Go race run | [sanitizer] enabled = ["race"] plus a runner command built or invoked with -race |
| Browser or JS engine | is_browser = "1", the product executable, and route-appropriate runner arguments |
The config is also part of triage:
attacker_controlsis read when deciding whether a crash trigger is a legitimate product input.- Reproduction export uses the repository URL, revision, build fields, and sanitizer paths to build a clean maintainer bundle.
A complete generic example¶
target = "libxml2"
upstream_url = "https://gitlab.gnome.org/GNOME/libxml2.git"
build_system = "cmake"
build_widening = true
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"]
Generated fields to review¶
| Field | Meaning |
|---|---|
target |
Target slug. It should match targets/<target> and output/<target>. |
upstream_url |
Source repository URL used as metadata in exported bundles. |
build_system |
Informational build-system label such as cmake, meson, autotools, mach, or gn. |
build_widening |
For ordinary native C/C++ targets, keep the canonical build and prepare one cached ASan sibling with compatible optional in-tree features enabled. Defaults to true when absent on a non-browser native target; set false to opt out. |
asan_bin |
ASan executable used by generic or browser runs. Relative paths resolve under targets/<target>/. An executable in the matching ASan build (or an external executable whose ASan instrumentation can be verified) is kept as you set it; bin/setup-target re-detects this field only to fill it or to replace a missing or mismatched path. |
asan_lib |
ASan library used when compiling C harness testcases. |
includes |
Include directories for C harness builds. Relative paths resolve under targets/<target>/. |
link_libs |
Extra linker inputs for C harness builds: system/library flags such as -lm, target-relative archives, or target-relative source files that must be compiled into the harness. A token containing $ is passed verbatim and never resolved as a path. |
is_browser |
"1" for browser mode, "0" for generic mode. |
One related field is not seeded: defines, the compiler define flags for
C/C++ harness builds (such as -DFOO=1). Add it by hand when a harness build
needs it, or run bin/auto-repair-target-toml to propose it after repeated
harness build failures (see
Target configuration).
Which fields you need depends on what the run will do:
- A generic CLI audit needs
asan_bin. - C harness testcases also need the selected sanitizer's library,
includes,defines, andlink_libs. - ASan uses top-level
asan_lib. UBSan, MSan, and TSan harnesses use[sanitizer].ubsan_lib,msan_lib, ortsan_lib.
If only the executable path is correct, a CLI-first audit can still run. Leave the C harness fields unresolved until you actually need public API harnesses.
Header-only libraries¶
Some C++ libraries ship only headers, with no static archive to link against.
- Leave
asan_libas the generatedFILL_MEcomment placeholder, or set it to an empty string. bin/export-reprowill emit areproduce.shthat compiles the harness directly against the target sources without a library link.includes,defines, andlink_libsstill apply normally.- If the harness later starts needing a real archive, replace
FILL_MEwith the path. The rest of the config does not change.
Optional fields¶
| Field | Meaning |
|---|---|
cmake_target |
CMake target name used when a generated bundle can rebuild a specific target. |
Build configurations¶
The canonical build-asan tree is always the regular-configuration control.
Build configurations add isolated, content-addressed ASan siblings; they never
replace that control or multiply the UBSan, MSan, and TSan build set.
build_widening = true asks TokenFuzz to derive one compatible widened
sibling from the working primary recipe. It enables advertised, in-tree
optional features while retaining the primary recipe's sanitizer and build
contract. If the project exposes no suitable options, no sibling is built and
the audit continues on the primary.
Declare configurations only for meaningful mutually exclusive modes that automatic widening cannot combine:
build_widening = true
[[build_config]]
name = "compact"
label = "compact table representation"
flags = ["-DENABLE_COMPACT=ON", "-DTABLE_BITS=8"]
features = ["compact tables"]
name must be a short lowercase identifier. flags are ordered configure
arguments: order and duplicates are preserved in the configuration identity.
features are human-readable surfaces shown to audit agents. A row uses
either non-empty flags or widen = true, not both. Refreshing generated
placeholders preserves operator-authored rows.
target.toml is parsed as strict TOML. Invalid section headers or malformed
arrays fail fast instead of silently falling back to top-level keys.
Sanitizers¶
The [sanitizer] section declares which sanitizer runners are intentionally
enabled for this target, and where to find each sanitizer's optional
suppression file.
Only ASan is enabled by default. The supported sanitizer slugs are asan,
ubsan, msan, tsan, and race; everything except asan is opt-in per
target. race (Go's runtime race detector) is valid only inside enabled. It
routes through [runner] and takes none of the per-sanitizer <name>_bin,
<name>_lib, or <name>_suppressions keys below. For when to enable each one
and the false-positive trade-offs, see
Sanitizer policy.
Findings-only mode (no sanitizer)¶
For targets that have no sanitizer build, typical for interpreted languages
(Python, Ruby, PHP, and so on) or JVM runtimes (Java, Kotlin), set enabled
to an explicit empty list:
With enabled = []:
bin/proberoutes testcases through[runner].bininstead of expecting an ASan binary.bin/run-asan genericskipsASAN_OPTIONSinjection so the language runtime sees a clean environment.- Runtime diagnostics (Python tracebacks, Go panics, Ruby exceptions, Java
stack traces, Node fatal errors, Rust panics, and so on) route to
findings/instead of being published as sanitizer crashes. Genuine sanitizer-class memory-safety signals (ASan, TSan, MSan, Go race detector) still stay incrashes/.
When [sanitizer] is absent entirely from target.toml, the default,
["asan"], applies. Only an explicit empty list opts the target out.
Per-sanitizer keys¶
| Key | Meaning |
|---|---|
enabled |
List of sanitizer slugs intentionally enabled for this target. Defaults to ["asan"]. |
<name>_suppressions |
Path to a suppression file. Appended via <NAME>_OPTIONS=suppressions=… at runner startup. Missing files emit a warning but do not abort. |
<name>_options |
Additional colon-separated runtime options appended to <NAME>_OPTIONS. |
ubsan_bin / msan_bin / tsan_bin |
Per-sanitizer binary overrides for opt-in runners. asan_bin is the top-level ASan binary field. |
ubsan_lib / msan_lib / tsan_lib |
Optional per-sanitizer library used when compiling C/C++ HARNESS: testcases. ASan uses top-level asan_lib. |
Example¶
asan_bin = "build-asan/xmllint"
[sanitizer]
enabled = ["asan", "msan"]
asan_suppressions = "build-asan/asan-suppressions.txt"
msan_suppressions = "build-msan/msan-suppressions.txt"
msan_bin = "build-msan/xmllint"
msan_lib = "build-msan/libxml2.a"
UBSan and TSan follow the same shape: add the slug to enabled and set the
matching <name>_bin, <name>_lib, and <name>_suppressions keys.
Notes:
- Paths are relative to
targets/<target>/unless absolute. - Relative paths whose first segment is
build-asan,build-ubsan,build-msan, orbuild-tsanareAUDIT_BUILD_SUFFIX-aware. Insidebin/audit-container-shell, those paths resolve to the per-image suffixed build directory; outside the container the suffix is empty. - Unknown sanitizer slugs in
enabledare logged on stderr and dropped. The loader falls back to["asan"]if[sanitizer]was absent and nothing valid remains. - An explicit empty list (
enabled = []) is honoured as findings-only mode and is not re-defaulted to["asan"]. - Runner scripts warn when invoked for a sanitizer that is not listed in
enabledbut do not abort. That keeps one-off reproduction and debugging commands usable.
Language runner¶
The [runner] section is the language-agnostic invocation contract. It is
used by bin/probe and bin/run-asan generic whenever no sanitizer binary is
configured: most commonly when [sanitizer] enabled = [], but also for
compiled-language targets that want to plug in a custom driver script.
| Key | Meaning |
|---|---|
bin |
Interpreter or driver program (python3, node, cargo, ruby, an absolute path to a wrapper script, and so on). A bare name is resolved on PATH first, then as a path relative to targets/<target>/, which is how a config points at a binary the target's own build produced. It runs with targets/<target>/ as its working directory, so a language whose dependency resolver reads the current directory (Go modules, for one) finds the audited package; testcase paths reach it absolute. |
args |
Literal argument list, with the runner tokens below substituted at run time. |
env |
Extra KEY=VAL strings layered on the runtime environment (for example ["GORACE=halt_on_error=1"] or ["PYTHONDEVMODE=1"]). The same tokens are substituted. |
crash_patterns |
Additional regex strings the triager treats as crash signals beyond its built-in language-agnostic markers. Use sparingly. |
success_codes |
Process exit codes from 0 through 123 that mean the runner completed normally. Defaults to [0]. bin/setup-target records the exit observed while validating the configured input route, accepting a nonzero code only after review confirms malformed-input rejection rather than startup or argv failure. 124 and above is where the timeout wrapper's own status, exec failures, and signal deaths live, so it is never accepted. A run whose output carries a sanitizer diagnostic is classified as a crash before its exit code is read, and calibration refuses an exit observed with one. The set describes the configured program only; an agent-built harness keeps 0 as its only success. |
Before model preflight or benchmark cells start, bin/audit and
bin/benchmark resolve any configured bin and verify that it is executable.
Standard language runners are also invoked with their version command, so an
installed launcher with a missing runtime (a java stub with no JDK, say)
fails immediately rather than burning model budget. bin is optional: a
findings-only target with no runner audits in code-review mode (testcase
execution is disabled, and probes report that); only a configured runner
that is unusable is a fatal startup error.
Runner tokens¶
| Token | Expands to |
|---|---|
{TESTCASE} |
Path to the testcase being run. |
{TARGET_ROOT} |
targets/<target>/. |
{RESULTS_DIR} |
This session's results/ directory. |
{TARGET_SLUG} |
The target slug. |
{SANITIZER} |
The selected sanitizer slug (asan, ubsan, …). |
{SWIFT_SANITIZER} |
The Swift spelling of that slug: address, undefined, or thread. Any other sanitizer is a hard error, not a silent empty value. |
{NULL_DEVICE} |
The platform's null device (/dev/null). |
{PROFILE} |
A fresh temporary browser profile. Valid only in browser execution; elsewhere it is an error. |
{TESTCASE} has one extra rule:
- When
{TESTCASE}appears inargs, it is replaced in place and the runner does not also append the testcase path. - When
{TESTCASE}is absent, the runner adds the testcase path after the expanded args, in the conventional last position.
Examples¶
# Pure Python target: interpreter + dev-mode env.
[runner]
bin = "python3"
args = ["{TESTCASE}"]
env = [
"PYTHONDEVMODE=1",
"PYTHONPATH={TARGET_ROOT}:{TARGET_ROOT}/src:{TARGET_ROOT}/lib",
]
crash_patterns = []
# Go target: findings-only driver via `go run`.
[runner]
bin = "go"
args = ["run", "{TESTCASE}"]
env = ["GORACE=halt_on_error=1"]
crash_patterns = []
To enable the Go runtime race detector, set [sanitizer] enabled = ["race"]
and use args = ["run", "-race", "{TESTCASE}"].
# Rust target: cargo run with the testcase path as an argument.
[runner]
bin = "cargo"
args = ["run", "--quiet", "--manifest-path", "{TARGET_ROOT}/Cargo.toml", "--", "{TESTCASE}"]
env = []
crash_patterns = []
# Swift package: the runner compiles with the selected Swift sanitizer
# (`address`, `undefined`, or `thread`). The argument before `{TESTCASE}`
# names the executable product to run, and is what audit preflight builds;
# replace `{TARGET_SLUG}` with the product's own name whenever the two
# differ, which they always do under a nested slug.
[runner]
bin = "swift"
args = ["run", "--quiet", "--disable-sandbox", "--skip-build", "-c", "release", "-Xswiftc", "-sanitize={SWIFT_SANITIZER}", "-Xswiftc", "-O", "--scratch-path", "{TARGET_ROOT}/.audit/swift-build-{SWIFT_SANITIZER}", "--package-path", "{TARGET_ROOT}", "{TARGET_SLUG}", "{TESTCASE}"]
env = []
crash_patterns = []
# Custom wrapper script: useful for Java/Kotlin builds that need a classpath
# or a wrapper that pre-configures JNI agents.
[runner]
bin = "./tools/run-testcase.sh"
args = ["{TESTCASE}"]
env = []
crash_patterns = ['^DEFENSIVE-ASSERT-FAILED:']
bin/setup-target emits a starter [runner] block driven by the detected
build system. The seeded values are commented when the build system is unknown
so the file is safe to parse before the operator fills it in.
Threat model¶
attacker_controls describes what an external caller can legitimately
control. Triage compares crash report Trigger source values against this
list, then lets the source reviewer correct that comparison from the code. A
settled review is reportable only when every required trigger component is in
the list: crafted bytes deciding the fault is not enough when the fault also
needs an application call order the list does not cover. A defect the
reviewer confirms is outside the list is rejected with a threat-model:
reason, its evidence kept under the rejected tree; one the reviews cannot
settle after the focused resolution is rejected as unsettled rather than left
without a verdict.
| Token | Meaning |
|---|---|
bytes |
Caller-controlled bytes: file, stream, packet, archive, media, regex, or similar data. |
call-sequence |
Ordered public API, script, plugin, 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. |
Unknown tokens are logged on stderr and ignored; if the resulting list is
empty, the loader defaults to ["bytes"]. The synonym call-order is
normalised to call-sequence.
Examples:
Browser mode¶
Generic targets:
Browser or browser-like runtime targets:
Browser mode enables:
- browser and JS testcase assumptions;
- coverage-gated browser or shell runs when available.
The browser binary and launch arguments are target metadata. For example:
asan_bin = "build-asan/MyBrowser.app/Contents/MacOS/MyBrowser"
[runner]
args = ["--user-data-dir={PROFILE}", "--headless=new", "--dump-dom", "{TESTCASE}"]
{PROFILE} expands to a fresh temporary profile directory for each browser
probe. bin/setup-target seeds launch arguments for structurally detected
browser build drivers; other browsers set them explicitly.
Session environment¶
At audit startup, bin/audit writes the active session file:
It contains dynamic values:
RESULTS_DIR;TARGET_ROOT;TARGET_SLUG;TARGET_REV;TARGET_REPO_TYPE;LOGDIR;SESSION_STARTED;TARGET_CONFIG_SHA256.
bin/probe discovers the nearest .session-env by walking upward from the
testcase path and current directory. Scratch testcases under results/
therefore do not need manual environment setup.
After preflight, bin/audit copies the target configuration to
output/<target>/<backend>/results/.target.toml and records its digest as
TARGET_CONFIG_SHA256. Every config consumer in that session (probes,
sanitizer runners, severity, report enrichment) reads the snapshot, so an edit
to the shared output/<target>/target.toml applies to the next run rather
than retargeting probes already contributing to this one. Editing or removing
the snapshot itself is a contract violation and fails loudly.
Strategy hints: [s6_peers]¶
[s6_peers] lists upstream peer projects to mine for S6 (cross-project
variant):
Empty or missing values are fine. The section only suggests additional
strategy material. bin/setup-target can also LLM-bootstrap a real
[threat_model] and [s6_peers] instead of the conservative defaults; you
can re-run that derivation at any time:
bin/suggest-threat-model <slug> --apply --force # re-derive attacker_controls
bin/suggest-peers <slug> --apply --force # re-derive [s6_peers]
bin/setup-target accepts --no-llm-config to keep the deterministic seed
and skip LLM enrichment. Use it when setup must stay offline; otherwise let
the suggestions run and review them.
The audited revision¶
target.toml records no revision. A revision written once at setup goes
stale the moment the checkout advances, and a stale commit in an exported
bundle or a report source link is a wrong answer that reads like a right one.
At audit startup the live source revision is written to .session-env as
TARGET_REV, which is exact for that run. Reports and exported bundles use
it, falling back to the checkout's own current revision when no session
recorded one.