Skip to content
Back to skills

2954 2b Rust Source Analyzer 220f9c1f

ASecurity

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.

  • 9 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 11, 2026
researchrustgoc++bashgitapi

Works with

  • api

Security analysis

A100/100

Scanned October 11, 2026

npx -y skills add tools-only/X-Skills --skill 2954-2b-rust-source-analyzer_220f9c1f --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 2954 2b Rust Source Analyzer 220f9c1f?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 2954 2b Rust Source Analyzer 220f9c1f
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-2954-2b-rust-source-analyzer-220f9c1f/badge)](https://www.skillsdirectory.com/skills/tools-only-2954-2b-rust-source-analyzer-220f9c1f)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

SKILL.md
---
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
allowed-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.

```bash
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:

```bash
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:

```bash
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`/`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:

```json
{
  "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:

```bash
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::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:

```json
{
  "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:
```json
{
  "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:
```json
{
  "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).

```json
{ "<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/`:

| File | Content |
|---|---|
| `sensitive-objects.json` | Appended Rust entries with `SO-5000+` IDs |
| `source-findings.json` | Appended Rust findings with `F-RUST-SRC-NNNN` IDs |
| `tu-map.json` | Updated with `{"<cargo_manifest>": "<rust_tu_hash>"}` if sensitive objects found |
| `rust-semantic-findings.json` | Intermediate output from `semantic_audit.py` (raw findings array or status-bearing error object) |
| `rust-dangerous-api-findings.json` | Intermediate output from `find_dangerous_apis.py` (raw findings array or status-bearing error object) |
| `rust-notes.md` | Summary: steps executed, finding counts by category, skipped steps and reasons |

## Finding ID Convention

| Entity | Pattern | Example |
|---|---|---|
| Rust sensitive object | `SO-5000+` | `SO-5001`, `SO-5002` |
| Rust source finding | `F-RUST-SRC-NNNN` | `F-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

| Category | Severity | Source |
|---|---|---|
| `MISSING_SOURCE_ZEROIZE` | medium–critical | Steps 2 + 3 |
| `SECRET_COPY` | low–critical | Steps 2 + 3 |
| `PARTIAL_WIPE` | medium–high | Step 2 |
| `NOT_ON_ALL_PATHS` | medium–high | Steps 2 + 3 |
| `OPTIMIZED_AWAY_ZEROIZE` | medium–high | Step 2 (flag at source; confirmed at IR in rust-compiler-analyzer) |

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.