Bug Class Taxonomy
The bug class taxonomy is a CWE-inspired hierarchical graph of security
vulnerability classes used by the llm_bug_class_selection threat model
strategy. It lives in stages/threat_model/bug_classes/research_concepts.json
and is loaded into BugClassTaxonomy at runtime.
Purpose
When ScanExecution.threat_model_strategy = "llm_bug_class_selection",
BugClassThreatModelStage loads the full taxonomy, presents it to the LLM,
and asks it to select the most relevant classes for the target codebase. The
selected classes focus both the threat model and the subsequent audit prompts.
Taxonomy models
BugClassCategory = Literal["pillar", "class", "base", "variant", "chain", "composite"]
BugClassSelectionDecision = Literal["select", "descend", "discard"]
@dataclass
class BugClass:
id: str
cwe_id: int | None
name: str
category: BugClassCategory
parent_id: str | None
child_ids: list[str]
description: str
source_url: str
@dataclass
class BugClassSelection:
bug_class_id: str
decision: BugClassSelectionDecision = "select"
confidence: str = "medium"
rationale: str = ""
in_scope_notes: list[str] = field(default_factory=list)
out_of_scope_notes: list[str] = field(default_factory=list)
@dataclass
class BugClassTaxonomy:
root_ids: list[str]
by_id: dict[str, BugClass]
ids_by_cwe: dict[int, str]
Abstraction levels
Each node has a category (abstraction level):
| Level | Meaning | Example |
|---|---|---|
pillar |
Security pillar | "memory-safety" |
class |
Vulnerability class | "use-after-free" |
base |
Specific pattern | "heap-uaf-concurrent-free" |
variant |
Implementation variant | "linux-rcu-uaf" |
chain |
Multi-step chain | "uaf-then-type-confusion" |
composite |
Complex combination | "reentrancy-via-signal-uaf" |
Coverage areas
The taxonomy (~40 nodes) spans these domains:
| Domain | Examples |
|---|---|
| Memory safety | Use-after-free, heap overflow, stack overflow, integer overflow, null dereference |
| Concurrency | Race conditions, TOCTOU, double-free under concurrency, lock misuse |
| Authorization | Privilege escalation, capability bypass, missing ownership checks |
| Injection | Command injection, SQL injection, path traversal, format string |
| Cryptography | Weak PRNG, key management, protocol implementation errors |
| Linux kernel | Reference counting (kref), RCU grace period violations, kobject lifetime, cgroup escapes |
| Smart contract | Reentrancy, integer overflow composites |
Selection decisions
The LLM evaluates each node and returns a BugClassSelection with a decision:
| Decision | Meaning |
|---|---|
"select" |
This class is in scope for the target codebase |
"descend" |
Pillar is relevant; examine child classes |
"discard" |
Not relevant to this codebase |
Only classes with decision="select" are included in the threat model output.
Selection schema
The agent output is validated against stages/threat_model/schemas/bug_class_selection.json.
Selected classes are written into the vega.threat_model artifact.
Manual override
Callers can bypass LLM selection entirely by providing explicit bug class IDs
via ScanIntent.bug_classes:
ScanIntent(
bug_classes=("use-after-free", "race-condition", "heap-buffer-overflow"),
)
When bug_classes is non-empty, BugClassThreatModelStage passes them
directly as pre-selected classes without the full taxonomy selection pass.
CWE mapping
Many nodes have a cwe_id that maps to MITRE CWE:
| Bug class ID | CWE |
|---|---|
use-after-free |
CWE-416 |
heap-buffer-overflow |
CWE-122 |
integer-overflow |
CWE-190 |
race-condition |
CWE-362 |
command-injection |
CWE-78 |
sql-injection |
CWE-89 |
path-traversal |
CWE-22 |
format-string |
CWE-134 |
BugClassTaxonomy.ids_by_cwe provides reverse lookup from CWE id to bug class id.
Plugin relationship
Plugins do not add bug classes to the taxonomy directly. Instead, LinuxPlugin
and WebApplicationPlugin influence bug class scope through:
output_schema_overrides(AUDIT)— replaces the auditbug_classenum with domain-specific values (kernel classes, OWASP classes).build_prompt_sections(AUDIT)— injects domain-specific vulnerability focus guidance into audit prompts.
The llm_bug_class_selection strategy is independent of plugin selection and
can be used with any plugin.