Audit Augmentation
Trail of BitsOfficialPublished by Trail of Bits
- Skill
- Tool integration
- Security
- CC-BY-SA-4.0
- No issues found
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
Audit Augmentation integrates external security findings into existing Trailmark code graphs. By mapping SARIF static analysis results, weAudit human-generated annotations, and binary-analysis graph exports to specific code nodes, it enables security researchers to visualize audit coverage and cross-reference findings with structural data like blast radius and taint analysis. This process creates severity-based subgraphs, allowing for more effective triage and prioritization of security issues within the context of the codebase.
What it does
- Projects SARIF static analysis results onto code graph nodes
- Imports human-generated weAudit annotations into the graph
- Integrates external binary-analysis graph exports for v0.4.0+ environments
- Creates severity-based subgraphs for findings
- Enables cross-referencing of findings with pre-analysis data like taint and blast radius
- Normalizes file paths and line ranges for accurate node matching
When to use it
- When you need to visualize audit findings alongside code structure
- When importing results from tools like Semgrep or CodeQL into a graph
- When incorporating human audit notes from weAudit into your analysis
- When you need to prioritize findings by cross-referencing them with blast radius or taint data
- When preparing findings for a triage workflow
Advantages
- Provides structural context to otherwise isolated security findings
- Supports both automated tool output and manual human audit annotations
- Facilitates advanced queries like finding high-severity issues on tainted nodes
- Standardizes disparate input formats into a unified graph representation
Usage examples
- “Augment my current Trailmark graph with the results from semgrep.sarif.”
- The agent runs the augmentation process, mapping SARIF findings to code nodes and creating relevant subgraphs for triage.
- “Import my weAudit annotations into the graph to see where high-severity issues are.”
- The agent processes the .weaudit file, annotates the corresponding nodes, and makes the weaudit:high subgraph available for querying.
Install
Download the skill as a ZIP:
https://autogineer.com/agent-skills/trailofbits/audit-augmentation/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip audit-augmentation.zip -d .agents/skills
Documentation by Trail of Bits
Audit Augmentation
Projects findings from external tools (SARIF) and human auditors (weAudit)
onto Trailmark code graphs as annotations and subgraphs. Trailmark 0.4.0+ can
also import an external binary-analysis graph JSON export via
engine.augment_binary().
When to Use
Importing Semgrep, CodeQL, or other SARIF-producing tool results into a graph
Importing weAudit audit annotations into a graph
Importing binary-analysis graph data into a source graph (Trailmark 0.4.0+)
Cross-referencing static analysis findings with blast radius or taint data
Querying which functions have high-severity findings
Visualizing audit coverage alongside code structure
Preparing one SARIF or weAudit result for
trailmark-finding-triage
When NOT to Use
Running static analysis tools (use semgrep/codeql directly, then import)
Building the code graph itself (use the
trailmarkskill)Generating diagrams (use the
diagramming-codeskill after augmenting)
Rationalizations to Reject
| Rationalization | Why It's Wrong | Required Action |
|---|---|---|
| "The user only asked about SARIF, skip pre-analysis" | Without pre-analysis, you can't cross-reference findings with blast radius or taint | Always run engine.preanalysis() before augmenting |
| "Unmatched findings don't matter" | Unmatched findings may indicate parsing gaps or out-of-scope files | Report unmatched count and investigate if high |
| "One severity subgraph is enough" | Different severities need different triage workflows | Query all severity subgraphs, not just error |
| "SARIF results speak for themselves" | Findings without graph context lack blast radius and taint reachability | Cross-reference with pre-analysis subgraphs |
| "weAudit and SARIF overlap, pick one" | Human auditors and tools find different things | Import both when available |
| "Tool isn't installed, I'll do it manually" | Manual analysis misses what tooling catches | Install trailmark first |
Installation
MANDATORY: If uv run trailmark fails, install trailmark first:
uv tool install trailmark
# Python snippets: uv run --with trailmark python - (a tool env is not importable)Version Gate
SARIF and weAudit augmentation are v0.2-safe. Binary graph augmentation is
Trailmark 0.4.0+ only. Before calling engine.augment_binary(), check:
if not hasattr(engine, "augment_binary"):
raise RuntimeError("Binary augmentation requires Trailmark >= 0.4.0")On Trailmark 0.5.0+, known links between source functions and imported binary
or external endpoints can also be declared once in .trailmark/links.toml
(see the main trailmark skill's Repository Links section) instead of being
re-derived per session. Declared external endpoints materialize as
proxy.external:<symbol> nodes on every parse.
Quick Start
CLI
# Augment with SARIF
uv run trailmark augment {targetDir} --sarif results.sarif
# Augment with weAudit
uv run trailmark augment {targetDir} --weaudit .vscode/alice.weaudit
# Both at once, output JSON
uv run trailmark augment {targetDir} \
--sarif results.sarif \
--weaudit .vscode/alice.weaudit \
--jsonBinary graph augmentation is programmatic in Trailmark 0.4.0+; do not invent a
CLI flag if trailmark augment --help does not show one.
Programmatic API
from trailmark.query.api import QueryEngine
engine = QueryEngine.from_directory("{targetDir}", language="auto")
# Run pre-analysis first for cross-referencing
engine.preanalysis()
# Augment with SARIF
result = engine.augment_sarif("results.sarif")
# result: {matched_findings: 12, unmatched_findings: 3, subgraphs_created: [...]}
# Augment with weAudit
result = engine.augment_weaudit(".vscode/alice.weaudit")
# Augment with an external binary graph export (v0.4+)
if hasattr(engine, "augment_binary"):
result = engine.augment_binary("binary_graph.json")
# Query findings
engine.findings() # All findings
engine.subgraph("sarif:error") # High-severity SARIF
engine.subgraph("weaudit:high") # High-severity weAudit
engine.subgraph("sarif:semgrep") # By tool name
engine.annotations_of("function_name") # Per-node lookupIf auto-detection is wrong for the target, rerun with an explicit language or
comma-separated list such as python,rust.
Workflow
Augmentation Progress:
- [ ] Step 1: Build graph and run pre-analysis
- [ ] Step 2: Locate SARIF/weAudit/binary graph files
- [ ] Step 3: Run augmentation
- [ ] Step 4: Inspect results and subgraphs
- [ ] Step 5: Cross-reference with pre-analysisStep 1: Build the graph and run pre-analysis for blast radius and taint context:
engine = QueryEngine.from_directory("{targetDir}", language="auto")
engine.preanalysis()If auto-detection is wrong for the target, rerun with an explicit language or
comma-separated list such as python,rust.
Step 2: Locate input files:
SARIF: Usually output by tools like
semgrep --sarif -o results.sariforcodeql database analyze --format=sarif-latestweAudit: Stored in
.vscode/<username>.weauditwithin the workspaceBinary graph (v0.4+): External JSON with
artifact,functions, andcallsfields. Trailmark imports this graph; it does not disassemble binaries itself.
Step 3: Run augmentation via engine.augment_sarif() or
engine.augment_weaudit(). For binary graphs, run engine.augment_binary()
only after the Version Gate succeeds. Check unmatched_findings in SARIF and
weAudit results — these are findings whose file/line locations didn't overlap
any parsed code unit.
Step 4: Query findings and subgraphs. Use engine.findings() to list all
annotated nodes. Use engine.subgraph_names() to see available subgraphs.
Step 5: Cross-reference with pre-analysis data to prioritize:
Findings on tainted nodes: overlap
sarif:errorwithtaintedsubgraphFindings on high blast radius nodes: overlap with
high_blast_radiusFindings on privilege boundaries: overlap with
privilege_boundary
For one candidate finding that needs a reachability verdict or PoC handoff,
continue with trailmark-finding-triage and use the augmented node as the
bound candidate.
Annotation Format
Findings are stored as standard Trailmark annotations:
Kind:
finding(tool-generated) oraudit_note(human notes)Source:
sarif:<tool_name>orweaudit:<author>Description: Compact single-line:
[SEVERITY] rule-id: message (tool)
Subgraphs Created
| Subgraph | Contents |
|---|---|
sarif:error | Nodes with SARIF error-level findings |
sarif:warning | Nodes with SARIF warning-level findings |
sarif:note | Nodes with SARIF note-level findings |
sarif:<tool> | Nodes flagged by a specific tool |
weaudit:high | Nodes with high-severity weAudit findings |
weaudit:medium | Nodes with medium-severity weAudit findings |
weaudit:low | Nodes with low-severity weAudit findings |
weaudit:findings | All weAudit findings (entryType=0) |
weaudit:notes | All weAudit notes (entryType=1) |
binary:<artifact> | Binary function nodes imported from a v0.4+ binary graph |
How Matching Works
Findings are matched to graph nodes by file path and line range overlap:
Finding file path is normalized relative to the graph's
root_pathNodes whose
location.file_pathmatches AND whose line range overlaps are selectedThe tightest match (smallest span) is preferred
If a finding's location doesn't overlap any node, it counts as unmatched
SARIF paths may be relative, absolute, or file:// URIs — all are handled.
weAudit uses 0-indexed lines which are converted to 1-indexed automatically.
Binary graph imports create origin=binary function nodes, origin=proxy
external proxy nodes for unresolved binary calls, and inferred
corresponds_to edges when a binary function maps back to a source node. The
expected JSON shape is intentionally small:
{
"artifact": {"name": "libexample", "architecture": "x86_64", "sha256": "..."},
"functions": [
{"symbol": "parse_packet", "address": "0x401000",
"source": {"file": "src/parser.c", "line": 42}}
],
"calls": [
{"source": "parse_packet", "target": "malloc", "confidence": "inferred"}
]
}Supporting Documentation
references/formats.md — SARIF 2.1.0 and weAudit file format field reference
Files
- ATTRIBUTION.mdAdded by AutoGineer939 B
- LICENSELicence file added by AutoGineer19.7 KiB
- SKILL.md9.1 KiB
- agents/openai.yaml245 B
- assets/trail-of-bits-mark.svg3.0 KiB
- references/formats.md3.5 KiB
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Needs: Needs Python, Needs Node.js
Security
No issues found by our static scan· No issues found
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Published by
- Trail of Bits
- Publisher
- Trail of Bits (Official)
- Source
- trailofbits/skills · plugins/trailmark/skills/audit-augmentation · commit e4dd0bb
- Licence
- Creative Commons Attribution-ShareAlike 4.0 International (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by Trail of Bits or Trail of Bits.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download audit-augmentation.zip