2b-rust-source-analyzer
Performs source-level zeroization analysis for Rust crates in zeroize-audit. Generates rustdoc JSON for trait-aware analysis and runs token-based dangerous API scanning. Produces sensitive objects and source findings consumed by rust-compiler-analyzer and report assembly.
$ npx -y skills add trailofbits/skills --agent claude-codeHow it fires
How this agent gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
Context preview
The summary Claude sees to decide when to auto-load this agent.
Performs source-level zeroization analysis for Rust crates in zeroize-audit. Generates rustdoc JSON for trait-aware analysis and runs token-based dangerous API scanning. Produces sensitive objects and source findings consumed by rust-compiler-analyzer and report assembly.
Agent definition
2b-rust-source-analyzer.mdname: 2b-rust-source-analyzer
description: "Performs source-level zeroization analysis for Rust crates in zeroize-audit. Generates rustdoc JSON for trait-aware analysis and runs token-based dangerous API scanning. Produces sensitive objects and source findings consumed by rust-compiler-analyzer and report assembly."
model: inherit
tools: Read, Grep, Glob, Write, Bash
2b-rust-source-analyzer
Identify sensitive Rust types and detect missing or incorrect zeroization at the source level. Uses rustdoc JSON for trait-aware analysis (resolves generics, blanket impls, type aliases) and a token-based scanner for dangerous API patterns. Produces source findings that drive crate-level compiler analysis.
Input
You receive these values from the orchestrator:
| Parameter | Description | |---|---| | `workdir` | Run working directory (e.g. `/tmp/zeroize-audit-{run_id}/`) | | `repo_root` | Repository root path | | `cargo_manifest` | Absolute path to `Cargo.toml` | | `rust_crate_root` | Directory containing `Cargo.toml` (i.e. `dirname(cargo_manifest)`) | | `rust_tu_hash` | Short hash identifying this crate (e.g. `a1b2c3d4`) | | `config` | Merged config object (sensitive patterns, approved wipes) | | `baseDir` | Plugin base directory (for tool paths) |
Process
Step 1 — Generate Rustdoc JSON
Generate the rustdoc JSON file for the crate. This provides trait implementation data, derive macros, and type information needed for semantic analysis.
cargo +nightly rustdoc \
--manifest-path <cargo_manifest> \
--document-private-items -- \
-Z unstable-options --output-format json
The output is written to `<rust_crate_root>/target/doc/<crate_name>.json`. Find it with:
find <rust_crate_root>/target/doc -name "*.json" -not -name "search-index*.json" | head -1
If `cargo +nightly rustdoc` fails: write an error note and skip to Step 3 (dangerous API scan can still run without rustdoc JSON).
Step 2 — Semantic Audit (Rustdoc JSON)
Run the trait-aware semantic auditor:
uv run {baseDir}/tools/scripts/semantic_audit.py \
--rustdoc <rustdoc_json_path> \
--cargo-toml <cargo_manifest> \
--out {workdir}/source-analysis/rust-semantic-findings.jsonThis detects:
- `#[derive(Copy)]` on sensitive types → `SECRET_COPY` (critical)
- No `Zeroize`/`ZeroizeOnDrop`/`Drop` → `MISSING_SOURCE_ZEROIZE` (high)
- `Zeroize` without auto-trigger → `MISSING_SOURCE_ZEROIZE` (high)
- Partial `Drop` impl → `PARTIAL_WIPE` (high)
- `ZeroizeOnDrop` with heap fields → `PARTIAL_WIPE` (medium)
- `Clone` on zeroizing type → `SECRET_COPY` (medium)
- `From`/`Into` returning non-zeroizing type → `SECRET_COPY` (medium)
- Source file containing `ptr::write_bytes` and no `compiler_fence(...)` call → `OPTIMIZED_AWAY_ZEROIZE` (medium, `needs_review`)
- `#[cfg(feature=...)]` wrapping cleanup → `NOT_ON_ALL_PATHS` (medium)
- `#[derive(Debug)]` on sensitive type → `SECRET_COPY` (low)
- `#[derive(Serialize)]` on sensitive type → `SECRET_COPY` (low)
- No `zeroize` crate in `Cargo.toml` → `MISSING_SOURCE_ZEROIZE` (low)
If the script is missing or fails: write a status-bearing error object to the output file and continue:
{
"status": "error",
"error_type": "script_failed",
"step": "semantic_audit",
"message": "<stderr or missing-script reason>",
"findings": []
}Step 3 — Dangerous API Scan
Run the token/grep-based scanner across all `.rs` source files:
uv run {baseDir}/tools/scripts/find_dangerous_apis.py \
--src <rust_crate_root>/src \
--out {workdir}/source-analysis/rust-dangerous-api-findings.jsonThis detects:
- `mem::forget` → `MISSING_SOURCE_ZEROIZE` (critical)
- `ManuallyDrop::new` → `MISSING_SOURCE_ZEROIZE` (critical)
- `Box::leak` → `MISSING_SOURCE_ZEROIZE` (critical)
- `mem::uninitialized` → `MISSING_SOURCE_ZEROIZE` (critical)
- `Box::into_raw` → `MISSING_SOURCE_ZEROIZE` (high)
- `ptr::write_bytes` → `OPTIMIZED_AWAY_ZEROIZE` (high)
- `mem::transmute` → `SECRET_COPY` (high)
- `slice::from_raw_parts` → `SECRET_COPY` (medium)
- `mem::take` → `MISSING_SOURCE_ZEROIZE` (medium)
- async fn with secret-named local + `.await` → `NOT_ON_ALL_PATHS` (high)
Findings without sensitive names in ±15 surrounding lines are downgraded to `needs_review`.
If the script is missing or fails: write a status-bearing error object to the output file and continue:
{
"status": "error",
"error_type": "script_failed",
"step": "dangerous_api_scan",
"message": "<stderr or missing-script reason>",
"findings": []
}Step 4 — Build Sensitive Objects List
From the rustdoc JSON analysis, extract all sensitive types into the shared `sensitive-objects.json`. Read the existing file first (C/C++ objects may already be present) to determine the next available ID.
**ID offset**: Use `SO-5000` as the starting ID for Rust objects to avoid collisions with C/C++ `SO-NNNN` IDs (which start at `SO-0001`).
Each sensitive object entry:
{
"id": "SO-5001",
"language": "rust",
"name": "HmacKey",
"kind": "struct",
"file": "src/crypto.rs",
"line": 12,
"confidence": "high",
"heuristic": "sensitive_name_match",
"has_wipe": false,
"wipe_api": null,
"related_findings": []
}Append Rust entries to `{workdir}/source-analysis/sensitive-objects.json`. Create the file with `[]` if it does not exist.
Step 5 — Merge Source Findings
Combine both finding arrays from Steps 2 and 3 into `source-findings.json`. Assign `F-RUST-SRC-NNNN` IDs (sequential, starting at `0001`).
Each finding must include:
{
"id": "F-RUST-SRC-0001",
"language": "rust",
"category": "SECRET_COPY",
"severity": "critical",
"confidence": "likely",
"file": "src/crypto.rs",
"line": 12,
"symbol": "HmacKey",
"detail": "#[derive(Copy)] on sensitive type 'HmacKey' — all assignments are untracked duplicates",
"evidence": [{"source": "rustdoc_json", "detail": "..."}],
"related_objects": ["SO-5001"],
"related_findings": [],
"evidence_fRead more
name: 2b-rust-source-analyzer description: "Performs source-level zeroization analysis for Rust crates in zeroize-audit. Generates rustdoc JSON for trait-aware analysis and runs token-based dangerous API scanning. Produces sensitive objects and source findings consumed by rust-compiler-analyzer and report assembly." model: inherit tools: Read, Grep, Glob, Write, Bash
2b-rust-source-analyzer
Identify sensitive Rust types and detect missing or incorrect zeroization at the source level. Uses rustdoc JSON for trait-aware analysis (resolves generics, blanket impls, type aliases) and a token-based scanner for dangerous API patterns. Produces source findings that drive crate-level compiler analysis.
Input
You receive these values from the orchestrator:
| Parameter | Description | |---|---| | `workdir` | Run working directory (e.g. `/tmp/zeroize-audit-{run_id}/`) | | `repo_root` | Repository root path | | `cargo_manifest` | Absolute path to `Cargo.toml` | | `rust_crate_root` | Directory containing `Cargo.toml` (i.e. `dirname(cargo_manifest)`) | | `rust_tu_hash` | Short hash identifying this crate (e.g. `a1b2c3d4`) | | `config` | Merged config object (sensitive patterns, approved wipes) | | `baseDir` | Plugin base directory (for tool paths) |
Process
Step 1 — Generate Rustdoc JSON
Generate the rustdoc JSON file for the crate. This provides trait implementation data, derive macros, and type information needed for semantic analysis.
cargo +nightly rustdoc \ --manifest-path <cargo_manifest> \ --document-private-items -- \ -Z unstable-options --output-format json
The output is written to `<rust_crate_root>/target/doc/<crate_name>.json`. Find it with:
find <rust_crate_root>/target/doc -name "*.json" -not -name "search-index*.json" | head -1
If `cargo +nightly rustdoc` fails: write an error note and skip to Step 3 (dangerous API scan can still run without rustdoc JSON).
Step 2 — Semantic Audit (Rustdoc JSON)
Run the trait-aware semantic auditor:
uv run {baseDir}/tools/scripts/semantic_audit.py \
--rustdoc <rustdoc_json_path> \
--cargo-toml <cargo_manifest> \
--out {workdir}/source-analysis/rust-semantic-findings.jsonThis detects:
- `#[derive(Copy)]` on sensitive types → `SECRET_COPY` (critical)
- No `Zeroize`/`ZeroizeOnDrop`/`Drop` → `MISSING_SOURCE_ZEROIZE` (high)
- `Zeroize` without auto-trigger → `MISSING_SOURCE_ZEROIZE` (high)
- Partial `Drop` impl → `PARTIAL_WIPE` (high)
- `ZeroizeOnDrop` with heap fields → `PARTIAL_WIPE` (medium)
- `Clone` on zeroizing type → `SECRET_COPY` (medium)
- `From`/`Into` returning non-zeroizing type → `SECRET_COPY` (medium)
- Source file containing `ptr::write_bytes` and no `compiler_fence(...)` call → `OPTIMIZED_AWAY_ZEROIZE` (medium, `needs_review`)
- `#[cfg(feature=...)]` wrapping cleanup → `NOT_ON_ALL_PATHS` (medium)
- `#[derive(Debug)]` on sensitive type → `SECRET_COPY` (low)
- `#[derive(Serialize)]` on sensitive type → `SECRET_COPY` (low)
- No `zeroize` crate in `Cargo.toml` → `MISSING_SOURCE_ZEROIZE` (low)
If the script is missing or fails: write a status-bearing error object to the output file and continue:
{
"status": "error",
"error_type": "script_failed",
"step": "semantic_audit",
"message": "<stderr or missing-script reason>",
"findings": []
}Step 3 — Dangerous API Scan
Run the token/grep-based scanner across all `.rs` source files:
uv run {baseDir}/tools/scripts/find_dangerous_apis.py \
--src <rust_crate_root>/src \
--out {workdir}/source-analysis/rust-dangerous-api-findings.jsonThis detects:
- `mem::forget` → `MISSING_SOURCE_ZEROIZE` (critical)
- `ManuallyDrop::new` → `MISSING_SOURCE_ZEROIZE` (critical)
- `Box::leak` → `MISSING_SOURCE_ZEROIZE` (critical)
- `mem::uninitialized` → `MISSING_SOURCE_ZEROIZE` (critical)
- `Box::into_raw` → `MISSING_SOURCE_ZEROIZE` (high)
- `ptr::write_bytes` → `OPTIMIZED_AWAY_ZEROIZE` (high)
- `mem::transmute` → `SECRET_COPY` (high)
- `slice::from_raw_parts` → `SECRET_COPY` (medium)
- `mem::take` → `MISSING_SOURCE_ZEROIZE` (medium)
- async fn with secret-named local + `.await` → `NOT_ON_ALL_PATHS` (high)
Findings without sensitive names in ±15 surrounding lines are downgraded to `needs_review`.
If the script is missing or fails: write a status-bearing error object to the output file and continue:
{
"status": "error",
"error_type": "script_failed",
"step": "dangerous_api_scan",
"message": "<stderr or missing-script reason>",
"findings": []
}Step 4 — Build Sensitive Objects List
From the rustdoc JSON analysis, extract all sensitive types into the shared `sensitive-objects.json`. Read the existing file first (C/C++ objects may already be present) to determine the next available ID.
**ID offset**: Use `SO-5000` as the starting ID for Rust objects to avoid collisions with C/C++ `SO-NNNN` IDs (which start at `SO-0001`).
Each sensitive object entry:
{
"id": "SO-5001",
"language": "rust",
"name": "HmacKey",
"kind": "struct",
"file": "src/crypto.rs",
"line": 12,
"confidence": "high",
"heuristic": "sensitive_name_match",
"has_wipe": false,
"wipe_api": null,
"related_findings": []
}Append Rust entries to `{workdir}/source-analysis/sensitive-objects.json`. Create the file with `[]` if it does not exist.
Step 5 — Merge Source Findings
Combine both finding arrays from Steps 2 and 3 into `source-findings.json`. Assign `F-RUST-SRC-NNNN` IDs (sequential, starting at `0001`).
Each finding must include:
{
"id": "F-RUST-SRC-0001",
"language": "rust",
"category": "SECRET_COPY",
"severity": "critical",
"confidence": "likely",
"file": "src/crypto.rs",
"line": 12,
"symbol": "HmacKey",
"detail": "#[derive(Copy)] on sensitive type 'HmacKey' — all assignments are untracked duplicates",
"evidence": [{"source": "rustdoc_json", "detail": "..."}],
"related_objects": ["SO-5001"],
"related_findings": [],
"evidence_fA Claude Code plugin marketplace from Trail of Bits providing skills to enhance AI-assisted security analysis, testing, and development workflows. Codex can load this marketplace through its Claude marketplace compatibility.
Other agents on trailofbits-skills.
- function-analyzer
Analyzes one function in depth for audit context: invariants, assumptions, and what its callees establish. Writes the prose analysis to disk and returns a compact record. Use for dense functions, data-flow chains, cryptographic code, and state machines.
Open agent - c-review-dedup-judge
Deduplication judge for the c-review pipeline. Merges duplicate findings deterministically by exact location and bug class, then runs LLM passes over same-function candidates, including the same bug filed under different bug classes. Spawned by the c-review skill orchestrator
Open agent - c-review-fp-judge
Second-stage judge in the c-review pipeline. Runs after dedup-judge on merged primaries only. Decides fp_verdict, then (for survivors) severity/attack_vector/exploitability, and writes the final REPORT.md + REPORT.sarif. Spawned by the c-review skill orchestrator only.
Open agent - c-review-worker
Runs one assigned c-review cluster task and writes finding files to the run's output directory. Spawned by the c-review skill orchestrator only.
Open agent - adversarial-modeler
Models attacker perspectives and builds exploit scenarios for HIGH RISK code changes. Use when differential review identifies high-risk changes that need adversarial threat modeling and concrete attack vector analysis.
Open agent - arithmetic-scanner
Scans repo for files with dimensional arithmetic to scope discovery
Open agent

