rust — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited rust (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
These guardrails apply to all Rust code you write, review, or modify. They exist because LLM-generated Rust tends to repeat the same classes of mistakes: lazy unwrap() calls, unnecessary cloning, overly broad visibility, and sloppy dependency management. Following these rules produces code that compiles cleanly, passes clippy, and looks like it was written by someone who actually ships Rust in production.
Rust's error handling is one of its greatest strengths — but only when used properly. The ? operator exists so you don't have to write boilerplate match arms, and crates like thiserror and anyhow exist so you don't have to hand-roll Display and Error impls.
? to propagate, or handle the error explicitly.#[derive(Debug, Error)] and #[error(...)] variants. This gives callers something to pattern-match on and produces clear error messages. thiserror is the right choice for both libraries and applications — the distinction is about where anyhow fits in, not whether to define error types.main(), CLI entry points, or top-level orchestration where you're collecting errors from multiple subsystems and just need to report them. anyhow::Result wraps your thiserror types; it never replaces them. If you find yourself writing anyhow::Result on an internal function, stop and define a proper error type instead.match result { Ok(v) => v, Err(e) => return Err(e) } when result? does the same thing.anyhow at the boundary, or use map_err to convert between your thiserror types deeper in the stack.Unnecessary cloning is the most common sign of "fighting the borrow checker" — it compiles, but it's wasteful and hides design problems. Think about whether a function actually needs to own data before taking it by value.
// clone needed: value used after move into spawned task).&str.String, they can pass &s; the reverse isn't free.Rust defaults to private for good reason. Every pub item is a commitment — it's part of your API surface and can't be removed without a breaking change.
pub(crate) instead of pub unless the item is genuinely part of the public API. Leave items private when they don't need to be accessed outside their module.Result or Option — a silently ignored error is a bug waiting to happen.Clone, PartialEq, Eq, Hash etc. when semantically appropriate._ — when you enumerate all variants explicitly, the compiler tells you when a new variant is added. Use _ only when the set is truly open-ended or when matching on values like integers/strings.match for single-variant checks — if let Some(x) = val { ... } is cleaner than a full match with a _ => {} arm.if !map.contains_key(&k) { map.insert(k, v); } when map.entry(k).or_insert_with(|| v) does the same thing in one lookup instead of two. The Entry API is also the right tool for counters (*entry.or_insert(0) += 1), default values, and conditional insertion. It's more efficient and signals intent clearly.Bad dependency choices haunt a project for years. A few minutes of due diligence saves a lot of pain.
serde, tokio, tracing, clap, thiserror, anyhow. These have large userbases, good docs, and responsive maintainers.tokio = "1" not tokio = "*". Wildcard versions invite breakage.toml_edit is appropriate). Avoid the toml crate — smol-toml is lighter and faster.tokio = { version = "1", default-features = false, features = ["rt-multi-thread", "macros"] }. This keeps compile times and binary size down.#[allow(clippy::...)] unless you have a genuine reason, documented with a comment explaining why the lint doesn't apply.lib.rs — this becomes the crate-level documentation.Rust's safety guarantees are its core value proposition. unsafe should be a last resort, not a convenience.
assert!(x == y) — the former gives you the actual vs. expected values on failure, which makes debugging far easier.Result, write tests that verify the error variants too.~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.