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.

Published by @Trail of Bits·from trailofbits/skills·0 agent reads / 30d·0 saves·

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:

ParameterDescription
workdirRun working directory (e.g. /tmp/zeroize-audit-{run_id}/)
repo_rootRepository root path
cargo_manifestAbsolute path to Cargo.toml
rust_crate_rootDirectory containing Cargo.toml (i.e. dirname(cargo_manifest))
rust_tu_hashShort hash identifying this crate (e.g. a1b2c3d4)
configMerged config object (sensitive patterns, approved wipes)
baseDirPlugin 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.json

This detects:

  • #[derive(Copy)] on sensitive types → SECRET_COPY (critical)
  • No Zeroize/ZeroizeOnDrop/DropMISSING_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.tomlMISSING_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.json

This detects:

  • mem::forgetMISSING_SOURCE_ZEROIZE (critical)
  • ManuallyDrop::newMISSING_SOURCE_ZEROIZE (critical)
  • Box::leakMISSING_SOURCE_ZEROIZE (critical)
  • mem::uninitializedMISSING_SOURCE_ZEROIZE (critical)
  • Box::into_rawMISSING_SOURCE_ZEROIZE (high)
  • ptr::write_bytesOPTIMIZED_AWAY_ZEROIZE (high)
  • mem::transmuteSECRET_COPY (high)
  • slice::from_raw_partsSECRET_COPY (medium)
  • mem::takeMISSING_SOURCE_ZEROIZE (medium)
  • async fn with secret-named local + .awaitNOT_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_files": []
}

Append Rust findings to {workdir}/source-analysis/source-findings.json. Create with [] if the file does not exist.

Step 6 — Update TU Map

Add the Rust crate entry to {workdir}/source-analysis/tu-map.json. Only add if at least one sensitive Rust object was found (otherwise no compiler-level analysis is needed).

{ "<cargo_manifest_path>": "<rust_tu_hash>" }

Read the existing tu-map.json first and merge; do not overwrite existing C/C++ entries.

Output

Write all output files to {workdir}/source-analysis/:

FileContent
sensitive-objects.jsonAppended Rust entries with SO-5000+ IDs
source-findings.jsonAppended Rust findings with F-RUST-SRC-NNNN IDs
tu-map.jsonUpdated with {"<cargo_manifest>": "<rust_tu_hash>"} if sensitive objects found
rust-semantic-findings.jsonIntermediate output from semantic_audit.py (raw findings array or status-bearing error object)
rust-dangerous-api-findings.jsonIntermediate output from find_dangerous_apis.py (raw findings array or status-bearing error object)
rust-notes.mdSummary: steps executed, finding counts by category, skipped steps and reasons

Finding ID Convention

EntityPatternExample
Rust sensitive objectSO-5000+SO-5001, SO-5002
Rust source findingF-RUST-SRC-NNNNF-RUST-SRC-0001

Sequential numbering within this agent run. Zero-padded to 4 digits.

Error Handling

  • rustdoc JSON generation fails: Write error to rust-notes.md, skip Step 2, continue with Step 3.
  • semantic_audit.py missing or fails: Write status-bearing error object to rust-semantic-findings.json, continue.
  • find_dangerous_apis.py missing or fails: Write status-bearing error object to rust-dangerous-api-findings.json, continue.
  • Both scripts fail: No Rust source findings. Write status-bearing error notes in both intermediate files and record source-analysis-partial-failure in rust-notes.md.
  • Always write sensitive-objects.json (even if unchanged from C/C++ run) and tu-map.json.
  • If the shared files (sensitive-objects.json, source-findings.json, tu-map.json) are missing, create them from scratch.

Categories Produced

CategorySeveritySource
MISSING_SOURCE_ZEROIZEmedium–criticalSteps 2 + 3
SECRET_COPYlow–criticalSteps 2 + 3
PARTIAL_WIPEmedium–highStep 2
NOT_ON_ALL_PATHSmedium–highSteps 2 + 3
OPTIMIZED_AWAY_ZEROIZEmedium–highStep 2 (flag at source; confirmed at IR in rust-compiler-analyzer)

Bundled with this artifact

1 file

Reference files that ship alongside this artifact. Agents pull these in only when the task needs them.

More on the bench

AGENT0

Comprehensive Review Security Auditor

Expert security auditor specializing in DevSecOps, comprehensive cybersecurity, and compliance frameworks. Masters vulnerability assessment, threat modeling, secure authentication (OAuth2/OIDC), OWASP standards, cloud security, and security automation. Handles DevSecOps integration, compliance (GDPR/HIPAA/SOC2), and incident response. Use PROACTIVELY for security audits, DevSecOps, or compliance implementation.

cybersecurity-soc+2
1
AGENT0

6 Test Generator

Generates runtime validation test harnesses (C tests, MSAN, Valgrind targets) for confirmed zeroize-audit findings. Produces a Makefile for automated test execution.

cybersecurity-soc+1
0
AGENT0

5c Poc Verifier

Verifies that each zeroize-audit PoC actually proves the vulnerability it claims to demonstrate. Reads PoC source code, finding details, and original source to check alignment between the PoC and the finding. Produces poc_verification.json consumed by the orchestrator.

cybersecurity-soc+1
0