Insights Business| SaaS| Technology Rust Supply Chain Security — Managing crates.io Risk in an Enterprise Codebase
Business
|
SaaS
|
Technology
Apr 29, 2026

Rust Supply Chain Security — Managing crates.io Risk in an Enterprise Codebase

AUTHOR

James A. Wondrasek James A. Wondrasek
Graphic representation of Rust supply chain security tooling and dependency auditing

On 5 December 2025, two malicious crates — finch-rust and sha-rust — were published to crates.io by a threat actor account named face-lessssss. Between them, 181 downloads. By 15:52 UTC the same day, both crates were deleted, the publisher account disabled, and associated GitHub repositories reported. Hours, not days.

Here is the relevant fact for anyone evaluating Rust adoption: crates.io’s own upload controls did not catch these crates. A third-party commercial monitoring service did. The attack worked at the upload stage.

This article looks at what the supply chain risk actually looks like, how it compares to npm and PyPI, and what governance tooling is available. If you are working through Microsoft’s Rust migration story and the broader case for enterprise Rust adoption, supply chain governance is one of the operational costs you need to price in before you commit.

What happened with the finch-rust and sha-rust malicious crates in December 2025?

Kush Pandya from Socket.dev‘s Threat Research Team detected both crates through behavioural heuristics and static analysis. He reported them to crates.io the same day. Carol Nichols and Adam Harvey from the Rust Foundation handled the response: account disabled, crates deleted, files retained for forensic analysis.

The payload was credential exfiltration. Neither crate had downstream dependents, and no confirmed payload execution has been reported.

The 2022 rustdecimal attack is the more useful comparison — a crate impersonating the popular rust_decimal library, with a cryptocurrency miner payload that real users downloaded before detection. finch-rust followed the same pattern but was caught faster. For context, the xz-utils backdoor (CVE-2024-3094) required two years of social engineering. finch-rust was opportunistic and low-sophistication by comparison.

For your risk register: crates.io does not perform automated malware scanning at upload. Detection relies on community reporting and third-party monitoring. The ecosystem’s detection capability is improving; its prevention capability at the registry level is still limited.

How is crates.io governed, and what does that mean for enterprise risk assessment?

The detection-versus-prevention gap that let finch-rust sit on the registry for ten days is a structural feature, not an oversight.

Jan David Nose, a full-time Rust Foundation employee, leads the Infrastructure Team that maintains crates.io. Fastly sponsors all bandwidth through its Fast Forward programme, providing enterprise-grade CDN infrastructure at no cost. Named, full-time staff, a dedicated security engineer, a clear escalation path. Not an anonymous open-source collective.

The risk vector worth paying attention to is authentication. crates.io uses GitHub OAuth as its primary login mechanism. A compromised GitHub account gives an attacker the ability to publish new crate versions under a legitimate publisher’s name — the same vector that triggered the npm Shai-Hulud attack in November 2025.

The mitigation is trusted publishing: short-lived OIDC tokens tied to CI identities rather than long-lived publish tokens on developer machines. If your organisation publishes crates, enabling trusted publishing is the highest-priority account security control. If you only consume crates, cargo-audit and cargo-deny are the relevant controls.

Why does Rust adoption cause a dependency count explosion, and is that a security problem?

The most useful data point comes from ClickHouse. When their team introduced Rust modules, Alexey Milovidov reported: “When we only used C++ we had 156 dependent C++ libraries… when we added Rust, the number of dependencies, even only Rust dependencies, became almost 700.”

That 4.5x multiplier is not a pathology — it is idiomatic Rust. The cultural norm is composing functionality from many small, focused crates. Each brings its own dependency tree.

A large dependency count is not inherently more dangerous than a small one. What increases risk is unreviewed, unpinned, and unmonitored dependencies. Cargo.lock pins every transitive dependency version deterministically, including SHA-256 checksums. Commit it. A committed Cargo.lock gives you reproducible builds and accurate SBOM generation. Without it committed, you cannot know exactly what is running in production.

At 700 dependencies, manual vetting is not viable. That is when cargo-audit and cargo-deny stop being optional and start being operational.

Is crates.io safer than npm or PyPI for enterprise use?

crates.io presents fewer incidents than npm, but not zero risk.

The npm Shai-Hulud worm (November 2025) compromised approximately 492 packages affecting Zapier, PostHog, Postman, and others. CISA issued a public alert. The finch-rust incident affected two crates and was contained the same day. Different orders of magnitude.

At roughly 160,000 crates compared to npm’s 2.3 million, crates.io has proportionally fewer abandoned packages and less typosquatting surface area.

The risk vector unique to Rust is build.rs. Build scripts execute arbitrary code on the developer machine at cargo build time — before any runtime security controls apply. A malicious build.rs can exfiltrate environment variables (including CI secrets), write to the filesystem, or make network connections during the build. Procedural macros present a related risk: arbitrary code in the compiler at build time. cargo-deny can flag crates that declare build scripts; it cannot audit what those scripts do.

For teams already managing npm supply chain risk: the governance discipline is comparable. The tooling is different, and build.rs is the one genuinely new vector to account for.

What are cargo-audit and cargo-deny, and which should my team adopt first?

Adopt cargo-audit first. It checks your Cargo.lock against the RustSec advisory database and surfaces known vulnerabilities by RUSTSEC identifier. Zero configuration required. You get immediate visibility into your current exposure.

Layer cargo-deny on top second, once your team has a dependency governance policy to encode. cargo-deny does advisory checks plus licence policy enforcement, banned-crates lists, and duplicate-dependency detection — all configured via a deny.toml file.

These tools are complementary, not alternatives. Many teams run both.

Making both tools mandatory CI steps is what converts awareness into enforcement — the difference between knowing about a vulnerability and being unable to merge code that introduces one.

What these tools cannot protect against: a malicious crate not yet reported to RustSec (the finch-rust attack window), and build.rs / proc macro execution. The finch-rust crates were live for ten days before detection. Any cargo-audit run during those ten days would have found nothing.

For teams requiring human-reviewed dependency chains, cargo-vet (Mozilla-initiated) records which crate versions have been reviewed by named individuals, with the audit file committed to version control.

What is an SBOM and how do enterprise Rust teams generate one?

A Software Bill of Materials (SBOM) is a machine-readable inventory of all software components and their dependencies. For Rust projects, it is generated from Cargo.lock, which already contains every pinned dependency version, source registry, and SHA-256 checksum.

If your organisation has not yet received an SBOM request from a customer or regulator, it will. FinTech teams face inquiries under DORA and NIS2. HealthTech teams get procurement questionnaires from hospital systems and insurers. Start generating before the first questionnaire arrives.

Two formats dominate. CycloneDX is the standard for practitioner and commercial security tool contexts — use this as your default. SPDX is preferred in government and compliance contexts. When in doubt, generate both — they take minutes from the same Cargo.lock input.

Two tools: cargo-cyclonedx generates CycloneDX; cargo-sbom generates SPDX. Both are cargo plugins requiring no additional infrastructure. Integrate SBOM generation into the release workflow, not on demand — a stale SBOM is as misleading as no SBOM.

How does an enterprise team vet a new Rust crate before adopting it?

Here is a practical five-step workflow for a 50–500 employee team without a dedicated security function.

Step 1 — Check advisories first. Add the candidate crate to a test branch and run cargo-audit. If advisories exist, assess severity before proceeding.

Step 2 — Inspect crate metadata on crates.io. Look for recent commit activity, a linked source repository, download count, and reverse dependency count. A crate depended on by hundreds of popular crates has more eyes on it than one with two dependents and a quiet commit history.

Step 3 — Review Cargo.toml for build script indicators. If the crate declares build = "build.rs", it executes arbitrary code at compile time. Flag these for additional review. This step has no npm equivalent — it is the primary adjustment Rust supply chain governance requires over your existing process.

Step 4 — Review the source repository. For crates with build scripts: check build.rs for unexpected network calls, filesystem writes, or environment variable access. For proc macros: confirm the macro only operates on its input token stream.

Step 5 — Record the review. Use cargo-vet to record which crate versions have been reviewed, by whom, and against which criteria. This prevents the same work being repeated across team members.

Once approved, pin the crate version in Cargo.lock and treat version bumps as deliberate decisions requiring re-vetting. For teams in regulated domains, see the dependency lifecycle management practices used in safety-critical environments.

How do I build a Rust dependency governance policy before incidents force one on my team?

The governance policy is what makes the tooling stack coherent. Without it, cargo-deny has nothing to enforce.

Five core policy elements:

  1. Approved licence list. MIT and Apache 2.0 are the Rust ecosystem defaults — uncontroversial for commercial use. LGPL, GPL, and AGPL require legal review. Encode this in deny.toml’s [licenses] section.

  2. Banned crates list. Codify crates prohibited by advisory, quality, or legal review in deny.toml’s [bans] section. cargo-deny check fails CI if any banned crate appears transitively.

  3. Advisory threshold. Block critical and high severity advisories, warn on medium.

  4. SBOM generation cadence. On every release build, CycloneDX format as default.

  5. Dependency pinning policy. Cargo.lock committed, no automatic updates, version bumps reviewed as pull requests with cargo-audit and cargo-deny as mandatory CI gates.

Prioritised adoption sequence from zero:

  1. Run cargo-audit in CI in report-only mode for two weeks. Understand your exposure without disrupting merges.
  2. Adopt cargo-deny with advisory blocking on high and critical severities.
  3. Add licence enforcement to deny.toml.
  4. Integrate SBOM generation into release builds using cargo-cyclonedx.
  5. Introduce cargo-vet if your criticality level warrants it.

The cost argument: roughly one engineering day to set up, a few hours per quarter to maintain. Compare that to a supply chain incident — engineering response, customer notification, potential regulatory disclosure. The discipline applies at all criticality levels; the rigour scales with risk.

Supply chain governance is one of several supply chain governance costs to account for as a migration planning input alongside toolchain investment and training. The case for Rust remains strong, and why Rust supply chain governance matters as adoption accelerates only becomes clearer as the ecosystem grows.

Frequently Asked Questions

Is crates.io safer than npm for enterprise use?

Measured by incident frequency and blast radius, the data favour crates.io. The December 2025 incident involved two crates contained the same day; the November 2025 npm Shai-Hulud worm affected 492 packages and triggered a CISA alert. crates.io’s smaller ecosystem means fewer abandoned packages and less typosquatting surface. The caveat: build.rs execution is a risk vector npm does not share in the same form.

How quickly can my team implement cargo-deny for an existing Rust codebase?

A basic advisory-blocking configuration can be running in CI within a few hours: install cargo-deny, initialise a deny.toml, add the check step to your pipeline. Full licence policy and banned-crates configuration takes an additional half-day to an engineering day.

What SBOM format should I use for Rust dependencies?

Use CycloneDX (via cargo-cyclonedx) as your default — it is the format most commercial security tools and enterprise procurement questionnaires accept. Use SPDX (via cargo-sbom) only if a specific customer, regulator, or government contract requires it.

What is the RustSec advisory database and how current is it?

A community-maintained database of security advisories for Rust crates, indexed by RUSTSEC identifiers. The RustSec Working Group maintains it on a rolling basis. Less comprehensive than npm’s advisory database — smaller ecosystem, shorter history — but actively maintained and consumed automatically by both cargo-audit and cargo-deny.

What is cargo-vet and do I need it?

cargo-vet (Mozilla-initiated) maintains an internal database of audited crate versions in a checked-in audit file. Adopt it if your organisation operates at high criticality or if procurement questionnaires require evidence of human review. For most SaaS teams, cargo-audit and cargo-deny are sufficient.

What is the build.rs supply chain risk and how serious is it?

Build scripts execute arbitrary code on the developer machine during cargo build, before any runtime security controls apply. A malicious build.rs can exfiltrate environment variables, write to the filesystem, or make network connections. cargo-deny can flag crates that declare build scripts but cannot audit what they do. Mitigate with manual review of build.rs in any newly added dependency and isolated CI environments with restricted network access.

How does cargo-audit differ from cargo-deny?

cargo-audit checks Cargo.lock against the RustSec advisory database — the detection tool; adopt it first, zero configuration required. cargo-deny performs the same checks plus licence policy enforcement, banned-crates enforcement, and duplicate dependency detection via deny.toml — the policy enforcement tool. Layer it on top once you have a governance policy to encode. Running both is common and recommended.

Can I configure cargo-deny to block specific crates by name?

Yes. The [bans] section of deny.toml accepts crate names and optional version ranges. cargo-deny check fails CI if any banned crate appears in the dependency tree, including transitively.

How did Socket.dev detect the finch-rust malicious crates?

Socket.dev uses static analysis and behavioural heuristics to scan newly published crates for suspicious patterns — unusual network calls, obfuscated code, package name impersonation. Kush Pandya detected the crates on December 5, 2025 through this monitoring. crates.io’s own upload controls did not catch them.

What happened with the rustdecimal incident and how does it compare?

In 2022, a threat actor published rustdecimal (impersonating rust_decimal) with a cryptocurrency miner payload. Real users downloaded it before detection. The finch-rust / sha-rust incident followed the same pattern but was detected within hours with no confirmed payload execution — three years of improving ecosystem response is visible in the comparison.

What does the Rust Foundation do about supply chain security?

The Rust Foundation employs full-time infrastructure engineers including Jan David Nose and Adam Harvey, and a dedicated security engineer who has conducted threat modelling on crates.io. It relies significantly on community reporting and third-party monitoring for incident detection. Its value for enterprise risk assessment is accountability and infrastructure commitment, not comprehensive automated scanning.

AUTHOR

James A. Wondrasek James A. Wondrasek

SHARE ARTICLE

Share
Copy Link

Related Articles

Need a reliable team to help achieve your software goals?

Drop us a line! We'd love to discuss your project.

Offices Dots
Offices

BUSINESS HOURS

Monday - Friday
9 AM - 9 PM (Sydney Time)
9 AM - 5 PM (Yogyakarta Time)

Monday - Friday
9 AM - 9 PM (Sydney Time)
9 AM - 5 PM (Yogyakarta Time)

Sydney

SYDNEY

55 Pyrmont Bridge Road
Pyrmont, NSW, 2009
Australia

55 Pyrmont Bridge Road, Pyrmont, NSW, 2009, Australia

+61 2-8123-0997

Yogyakarta

YOGYAKARTA

Unit A & B
Jl. Prof. Herman Yohanes No.1125, Terban, Gondokusuman, Yogyakarta,
Daerah Istimewa Yogyakarta 55223
Indonesia

Unit A & B Jl. Prof. Herman Yohanes No.1125, Yogyakarta, Daerah Istimewa Yogyakarta 55223, Indonesia

+62 274-4539660
Bandung

BANDUNG

JL. Banda No. 30
Bandung 40115
Indonesia

JL. Banda No. 30, Bandung 40115, Indonesia

+62 858-6514-9577

Subscribe to our newsletter