Skip to main content

Configuration files

speca init produces two JSON files under outputs/. They are the only inputs the pipeline needs from you. This page is the canonical schema reference.

outputs/TARGET_INFO.json

Identifies the codebase under audit. Read by Phase 02c (to clone the right commit) and Phase 03 (to resolve relative paths).

{
"project_name": "lighthouse-audit-2026-05",
"target_repo": "https://github.com/sigp/lighthouse",
"target_commit": "v5.1.3",
"target_language": "Rust",
"target_layer": "consensus",
"description": "Lighthouse Ethereum consensus client, v5.1.3"
}
FieldRequiredNotes
project_nameyesUsed in output paths and report titles
target_repoyesPublic Git URL. SSH URLs are accepted if your SSH agent can reach them
target_commityesCommit hash, branch, or tag. Pinning to a tag/hash is strongly recommended for reproducibility
target_languageyesFree-form label; tree_sitter MCP picks the right parser based on file extensions, not this field
target_layernoHint used by Phase 01e to bias which CWE templates apply
descriptionnoFree-form note for the report

The repository is cloned under target_workspace/ at run time; you do not commit it.

outputs/BUG_BOUNTY_SCOPE.json

Defines what counts as in-scope and how severity is assigned. Required by Phase 01e — the orchestrator aborts with sys.exit(1) if it is missing.

{
"program_name": "ethereum-fusaka",
"scope_version": "1.0",

"in_scope": [
"src/consensus/",
"src/crypto/kzg.rs",
"src/state_machine.rs"
],

"out_of_scope": [
"tests/",
"docs/",
"vendor/",
"build/"
],

"severity_classification": {
"CRITICAL": {
"description": "Protocol halt, cryptographic break",
"cwe": ["CWE-327", "CWE-338"],
"examples": ["Invalid signature verification", "Entropy exhaustion"]
},
"HIGH": {
"description": "State divergence, consensus failure",
"cwe": ["CWE-862", "CWE-863"],
"examples": ["Unauthorized state transition", "Access control bypass"]
},
"MEDIUM": {
"description": "Information disclosure, partial bypass",
"cwe": ["CWE-200", "CWE-203"],
"examples": ["Timing leak", "Nonce reuse"]
},
"LOW": {
"description": "Quality, usability",
"cwe": ["CWE-400"],
"examples": ["Resource leak", "Performance degradation"]
}
},

"scope_notes": "Only in-scope high-value code paths will be audited."
}

Top-level fields

FieldRequiredNotes
program_nameyesIdentifier; appears in report headings
scope_versionnoVersion label, e.g. when re-running with a tightened scope
in_scopeyesGlob/path entries. Phase 04 Gate 3 keeps findings whose code path matches at least one
out_of_scopenoExplicit excludes. Findings landing here are returned as DISPUTED_FP by Gate 3
severity_classificationyesMaps levels (CRITICAL / HIGH / MEDIUM / LOW / Informational) to CWE references and examples
scope_notesnoFree-form notes propagated into reports

Why severity goes here, not in the code

Severity is a program-specific judgment (a "100% validators stuck" issue is CRITICAL in a consensus client and HIGH elsewhere). Phase 02c uses severity_classification to drop Informational properties before audit; Phase 03 reads it for context; Phase 04 calibrates the final severity. Centralizing it in this file is what makes the rest of the pipeline contest-agnostic — see Operations / Reproducing RQ1 for an example of swapping rubrics.

Sharing a rubric across implementations

For multi-implementation audits (e.g. ten Ethereum clients implementing the same EIP), use a common_rubric block to reuse a single scope description:

{
"program_name": "kzg-batch-verify-v2",
"common_rubric": {
"in_scope": [
"KZG parameter generation (setup)",
"Commitment creation",
"Batch verification (main algorithm)",
"Polynomial operations"
],
"out_of_scope": [
"Serialization / deserialization",
"Performance optimizations",
"Logging / debugging"
]
}
}

Each implementation then inherits the same property vocabulary, which is what enables cross-implementation comparison.

Sanity checks

speca doctor verifies that both files load and their severity_classification parses. If you author them by hand, run:

speca doctor

before kicking off speca run. It reports the first parse error with line + column.