Rust
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Ownership and Borrowing
-
Section 4: Structuring Data
-
Section 5: Collections and Error Handling
-
Section 6: Traits and Generics
-
Section 7: Concurrency
-
Section 8: Building for the Web
-
Section 9: Memory and Performance
-
Section 10: More Standard Library and Ecosystem
-
Section 11: Advanced Rust
-
Section 12: Rust for Systems and WebAssembly
-
Section 13: Tooling and Best Practices
-
Section 14: Data Structures and Algorithms in Rust
-
Section 15: Practical Projects
-
Section 16: Interview Practice
-
Section 17: std::collections In Depth
-
Section 18: std::io and std::fs In Depth
-
Section 19: std::net
-
Section 20: std::option and std::result In Depth
-
Section 21: std::iter In Depth
-
Section 22: std::sync In Depth
-
Section 23: std::string and std::str
-
Section 24: Cargo and Crates.io Ecosystem
-
Section 25: Popular Crates Ecosystem
-
Section 26: Rust Memory Model Deep Dive
-
Section 27: More Practice Exercises
-
Section 28: More Interview Practice
-
Section 29: Async Rust Deep Dive
-
Section 30: Tokio Ecosystem In Depth
-
Section 31: Error Handling Ecosystem Deep Dive
-
Section 32: Serde In Depth
-
Section 33: Web Development with Rust Deep Dive
-
Section 34: Database Access Ecosystem
-
Section 35: Rust for Embedded Systems Deep Dive
-
Section 36: Rust Macros In Depth
-
Section 37: Advanced Trait System
-
Section 38: Unsafe Rust In Depth
-
Section 39: Rust CLI Development
-
Section 40: Testing Ecosystem Deep Dive
-
Section 41: WebAssembly Deep Dive
-
Section 42: Rust Design Patterns
-
Section 43: More Data Structures in Rust
-
Section 44: Final Practice Projects
-
Section 45: Rust Performance Optimization
-
Section 46: Rust Ecosystem Tooling
-
Section 47: More Interview and Review
242: cargo-audit for Security Scanning
Here is a situation I've run into more times than I'd like to admit: you've built a tool, it passes all your tests, and the logic is sound. You're feeling great. But beneath the surface, in your Cargo.lock file, you're carrying a "time bomb"—a dependency with a known security vulnerability (CVE) that could allow an attacker to crash your server or leak memory.
# Cargo.toml
[dependencies]
# Imagine we are using an older version of a crate for compatibility
# that has a known vulnerability in its parsing logic.
some-parsing-crate = "0.1.0"
tokio = { version = "1.0", features = ["full"] }
If you run cargo check or cargo test, everything looks perfect. The compiler doesn't care if a crate has a security flaw; it only cares if the code is valid Rust. This is why "it works on my machine" is a dangerous phrase when it comes to security.
The invisible vulnerability in Cargo.lock
The problem is that your dependency tree is deep. You might not even be using some-parsing-crate directly; it could be a dependency of a dependency. Since Cargo.lock pins exact versions, you stay on that vulnerable version indefinitely unless you manually update or run cargo update. But even then, how do you know which versions are actually dangerous?
I used to manually check security mailing lists, which is a great way to waste your entire Tuesday. Instead, we use cargo-audit. This tool scans your Cargo.lock and compares it against the RustSec Advisory Database—a community-curated list of crates with reported vulnerabilities.
Automating the hunt with cargo-audit
First, you need to install the tool. It's not part of the standard Rust toolchain, so you'll grab it via cargo:
cargo install cargo-audit
Now, let's see what happens when we run it on our project:
$ cargo audit
Scanning Cargo.lock for vulnerabilities...
Found 1 vulnerability!
Crate: some-parsing-crate
Version: 0.1.0
Advisory: RUSTSEC-2023-XXXX
Title: Buffer overflow in parser
URL: https://rustsec.org/advisories/RUSTSEC-2023-XXXX
Keyword: [denial-of-service]
Fixed-in: 0.1.1
The output is explicit. It tells us exactly which crate is the problem, why it's a problem (Buffer overflow), and most importantly, which version fixes it (0.1.1). I usually check the URL provided in the output to understand if the vulnerability actually affects the way I'm using the crate, but in most cases, the rule is simple: update immediately.
To fix this, we update our dependencies. If we pinned the version in Cargo.toml, we update it there. If it's a transitive dependency, we can try:
cargo update -p some-parsing-crate
Running cargo audit again should now return a clean bill of health: Scanning Cargo.lock for vulnerabilities... All crates are up to date!
I highly recommend adding this to your CI/CD pipeline. There is nothing quite as humbling as having your build fail because a crate you haven't touched in six months suddenly got a security advisory. It's better to find out during a PR check than during a post-mortem meeting.
📋 Practical Task
Securing a Legacy Dependency Tree
In this exercise, you will simulate a security audit on a project with a known vulnerable dependency.
- Create a new Rust project called
security-scan-demo. - Add the following dependency to your
Cargo.toml:# Use an old version of a crate known for vulnerabilities, such as an old version of `yum` or `nom` if available, or simply use a crate you know has a CVE history. For this exercise, use:scroll = "0.9.0"(which has known historical vulnerabilities). - Install
cargo-auditusingcargo install cargo-audit. - Run
cargo auditand identify the specific RUSTSEC advisory ID associated with the vulnerability. - Update the
scrollcrate to the latest patched version in yourCargo.toml. - Run
cargo auditagain to verify that the vulnerability has been resolved.
There are no comments for now.