rgoussu@goussu: ~/library/rust/testing
~/library/rust/testing cat security-testing.md

Security testing — audit, unsafe hygiene & fuzzing

# The Rust security-testing portfolio — cargo-audit/deny/vet on the supply chain, cargo-geiger and miri on unsafe code, fuzzing the input surface, and SAST's smaller role.

Conceptsaved 2026-08-09 #rust#testing#security#supply-chain#unsafe

Overview

Security testing in Rust concentrates where Rust's risks actually are. Memory safety removes the classic C/C++ bug classes from safe code, so the portfolio tilts toward three fronts: the supply chain (a deep, fine-grained dependency graph whose build scripts run arbitrary code), the unsafe surface (small but load-bearing), and the input boundary (parsers and protocols, where panics become DoS). The scanner-heavy SAST culture of the Java portfolio has a correspondingly smaller role here.

Key points

  • Supply chain first: cargo audit (RustSec advisories against Cargo.lock), cargo deny (advisories + licenses + source policy as a CI gate), cargo vet (human-audit records) — mechanics in Building & releasing; this is the row every Rust CI needs.
  • Unsafe hygiene is auditable: cargo geiger counts and locates unsafe across the dependency tree (an exposure metric, not a verdict); #![forbid(unsafe_code)] on crates that should have none turns the metric into a guarantee; miri checks the unsafe that remains for actual UB.
  • Fuzz the boundary: every deserializer, framing layer and file-format parser gets a cargo-fuzz target; in Rust the typical finding is a panic or resource-exhaustion path — a denial-of-service bug class, reachable from safe code, and the most common real-world Rust CVE shape alongside logic flaws.
  • Panics are the forgotten attack surface: unwrap on attacker-controlled input is a remote crash; clippy's unwrap_used/expect_used restriction lints, panic = abort consequences, and load-shedding limits (web security) are the mitigations.
  • SAST exists, scaled to need: clippy's correctness/suspicious classes catch API-misuse patterns; semgrep has Rust rules; there is no FindSecBugs-scale ecosystem because injection-style sinks are rarer — the type system and parameterized queries by construction close most of them.
  • DAST is language-agnostic: ZAP/Burp against a staging deployment work the same as ever; nothing Rust-specific to add beyond the E2E harness to drive it.
  • Sanitizers still matter at the FFI edge: -Zsanitizer=address (nightly) for mixed Rust/C binaries — memory safety promises stop at extern "C".

Details

The portfolio, one row each

Front Tool Cadence
Known-vuln dependencies cargo-audit / cargo-deny Every CI run
Dependency trust cargo-vet (+ lockfile discipline, --locked) On dependency change
Unsafe exposure cargo-geiger, #![forbid(unsafe_code)] Audit checkpoints
UB in unsafe code miri, sanitizers at FFI CI on unsafe-bearing crates
Input surface cargo-fuzz targets, proptest no-panic properties Nightly / continuous (OSS-Fuzz)
Runtime posture ZAP/Burp on staging, security headers checks Pre-release

Related