Skills audit-augmentation
install
source · Clone the upstream repo
git clone https://github.com/trailofbits/skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/trailofbits/skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/trailmark/skills/audit-augmentation" ~/.claude/skills/trailofbits-skills-audit-augmentation && rm -rf "$T"
manifest:
plugins/trailmark/skills/audit-augmentation/SKILL.mdsource content
Audit Augmentation
Projects findings from external tools (SARIF) and human auditors (weAudit) onto Trailmark code graphs as annotations and subgraphs.
When to Use
- Importing Semgrep, CodeQL, or other SARIF-producing tool results into a graph
- Importing weAudit audit annotations into a graph
- Cross-referencing static analysis findings with blast radius or taint data
- Querying which functions have high-severity findings
- Visualizing audit coverage alongside code structure
When NOT to Use
- Running static analysis tools (use semgrep/codeql directly, then import)
- Building the code graph itself (use the
skill)trailmark - Generating diagrams (use the
skill after augmenting)diagramming-code
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 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 |
| "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 pip install trailmark
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 \ --json
Programmatic API
from trailmark.query.api import QueryEngine engine = QueryEngine.from_directory("{targetDir}", language="python") # 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") # 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 lookup
Workflow
Augmentation Progress: - [ ] Step 1: Build graph and run pre-analysis - [ ] Step 2: Locate SARIF/weAudit files - [ ] Step 3: Run augmentation - [ ] Step 4: Inspect results and subgraphs - [ ] Step 5: Cross-reference with pre-analysis
Step 1: Build the graph and run pre-analysis for blast radius and taint context:
engine = QueryEngine.from_directory("{targetDir}", language="{lang}") engine.preanalysis()
Step 2: Locate input files:
- SARIF: Usually output by tools like
orsemgrep --sarif -o results.sarifcodeql database analyze --format=sarif-latest - weAudit: Stored in
within the workspace.vscode/<username>.weaudit
Step 3: Run augmentation via
engine.augment_sarif() or
engine.augment_weaudit(). Check unmatched_findings in the result — 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
withsarif:error
subgraphtainted - Findings on high blast radius nodes: overlap with
high_blast_radius - Findings on privilege boundaries: overlap with
privilege_boundary
Annotation Format
Findings are stored as standard Trailmark annotations:
- Kind:
(tool-generated) orfinding
(human notes)audit_note - Source:
orsarif:<tool_name>weaudit:<author> - Description: Compact single-line:
[SEVERITY] rule-id: message (tool)
Subgraphs Created
| Subgraph | Contents |
|---|---|
| Nodes with SARIF error-level findings |
| Nodes with SARIF warning-level findings |
| Nodes with SARIF note-level findings |
| Nodes flagged by a specific tool |
| Nodes with high-severity weAudit findings |
| Nodes with medium-severity weAudit findings |
| Nodes with low-severity weAudit findings |
| All weAudit findings (entryType=0) |
| All weAudit notes (entryType=1) |
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_path - Nodes whose
matches AND whose line range overlaps are selectedlocation.file_path - The 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.
Supporting Documentation
- references/formats.md — SARIF 2.1.0 and weAudit file format field reference