cargo geiger: counting unsafe Rust across a whole dependency graph
Detects usage of unsafe Rust in a Rust crate and its dependencies.
At a glance
- What is it?
- A cargo subcommand that reports how much unsafe code sits in your crate and in everything it pulls in, with no judgement attached. Useful as an input to an audit, useless as a pass or fail gate on its own, and the README is careful to say so.
- Who is it for?
- Adopt cargo-geiger when you want a dependency wide picture of unsafe code before an audit, since running it once across a lockfile answers a question that reading your own source cannot. Do not adopt it as a compliance gate, because the README states explicitly that the tool does not advise whether code is truly insecure, and a crate with zero unsafe functions can still be unsound through a dependency.
- Can I use it commercially?
- Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
- Is it still maintained?
- Yes. The repository last received commits 25 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 7, 2026, and from our analysis. They are not legal advice.
Star history
- geiger-rs/cargo-geiger1,664 ★ · +10
| Repository | 2026-10-16 | 2026-11-07 |
|---|---|---|
| geiger-rs/cargo-geiger | 1.7k | 1.7k |
10 Stars in the last 22 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
A measurement tool that refuses to render a verdict
cargo-geiger lists statistics about unsafe Rust usage in a crate and all of its dependencies. That is the entire scope, stated plainly in the README.
What makes it interesting is the second half of that sentence. Almost every other unsafe audit tool you would reach for looks at a single crate, and the interesting question is usually about the crates you did not write. Counting unsafe across the whole resolved graph turns that into a table you can read.
The README is unusually explicit about what the numbers are not for. It states the tool is not meant to advise directly whether code is ultimately truly insecure, and that the purpose is to provide statistical input to auditing, for example alongside cargo-crev or safety-dance. It also makes the underlying point that the use of unsafe is nuanced and necessary in some cases, and that any motivation for using it is outside the scope of the tool.
Then it asks that reporting be handled with care, and links to a discussion of the stigma around unsafe on Reddit, a talk by Jon Gjengset on demystifying unsafe code, and the Rust language unsafe code guidelines working group document. That is a project arguing against its own most tempting misuse, which is rare enough to be worth respecting.
The name comes from the Geiger counter, with the stated reasoning that unsafe code, like ionizing radiation, is unavoidable in some situations and should be safely contained.
Two install paths, one of which statically links OpenSSL
Installation is a cargo install, with a variant for environments where a system OpenSSL is not what you want:
cargo install --locked cargo-geigerThe plain form looks for and uses a system wide installed OpenSSL library. The alternative builds and statically links OpenSSL into the executable:
cargo install --locked cargo-geiger --features vendored-opensslThe --locked flag appears in both, which is the right call for a tool you might install in CI where the build should be reproducible.
Pre-built binaries are also available from the GitHub releases page, which is the option to take if you would rather not compile it at all.
There is a container path as well. The Dockerfile in the repository root is a four stage build on the rust image: a planner stage installs cargo-chef and runs cargo chef prepare to produce recipe.json, a cacher stage runs cargo chef cook --release, a builder stage assembles the binary with cargo build --release --bin cargo-geiger, and a runtime stage copies just that binary to /usr/local/bin with an ENTRYPOINT of cargo-geiger. A .dockerignore sits at the root for the same reason.
The four stage structure is the standard cargo-chef pattern and exists to keep layer caching useful when only source files change.
Usage is one command in the crate directory
The usage section is two steps: navigate to the same directory as the Cargo.toml you want to analyze, then run the subcommand.
cargo geigerThere is no flag documentation in the README, no output format description beyond a screenshot, and no mention of a machine readable mode in the text available here. That is a real limitation for adoption, because a table you can only read by eye is fine for an audit and useless for a dashboard.
If you need the format, the practical route is to run it and look, or to read the serde library described below.
The plugin form matters for one practical reason: as a cargo subcommand it inherits your working directory and your resolved dependency graph, so it sees whatever is in your Cargo.lock. This can produce a confusing first run. That is standard cargo behaviour, but it is the kind of thing that produces a confusing first run.
Three libraries, one of them explicitly unstable
The README documents three exposed libraries, and the warning on the first one is unusually clear.
cargo-geiger is described as an unversioned and highly unstable library exposing the internals of the cargo-geiger binary, and the README says any function it contains may be subject to change. That is not a semver stability promise in any direction.
cargo-geiger-serde is a library containing the serializable report types. This is the one to look at if you want to build tooling on top, because report types that can be serialized are the difference between parsing a screenshot and parsing a value.
geiger is described as a library containing a few decoupled cargo components used by cargo-geiger. Decoupled is the meaningful word: it suggests the dependency graph walking lives separately from the reporting, which is why a third crate exists at all.
The Cargo.toml confirms the layout as a three member workspace with members cargo-geiger, cargo-geiger-serde and geiger.
That workspace also excludes seven directories under test_crates/, which is more informative than any test count would be. The exclusions are named for what they exercise: a package with no deps, a package with shallow deps, a package with nested deps, a workspace with a top level package, a workspace with a virtual manifest, a package whose cargo lock is out of date, and a package with a patched dependency. Each of those is a case where a dependency graph tool can silently do the wrong thing, and each has its own fixture crate.
Project identity has moved, and the README still points at the old paths
Something to know before you file anything: the repository you are reading is geiger-rs/cargo-geiger, and the README's links mostly do not point at it.
The changelog link goes to github.com/rust-secure-code/cargo-geiger/blob/master/CHANGELOG.md, and the known issues section points at the issue tracker at github.com/rust-secure-code/cargo-geiger/issues. Meanwhile the crates.io links are current and the repository itself is the geiger-rs one.
In other words, the project has a new home and the documentation has not fully followed. For a user this mostly matters in one place: where to report a bug. Following the README's issue link takes you to the old organisation rather than the repository you cloned.
The licence is listed as unknown, and no LICENSE file appears among the top level entries, where LICENSE would sit if it existed. That is a genuine adoption question for a security tool you might want to vendor or redistribute, and it is not resolvable from the README.
Release history is healthy and recent. The last push was on 2026-10-14, and releases are v0.14.0 on 2026-10-12, cargo-geiger-0.13.0 on 2025-08-31 and cargo-geiger-0.12.0 on 2025-04-10. Note that the newest release is named geiger-0.14.0 rather than cargo-geiger-0.14.0, which matches the workspace split and suggests the packages are versioned independently.
There is a matrix.json at the repository root alongside a CI badge, which is the configuration for the CI test matrix across Rust versions, and a Dockerfile for container builds.
Where it is the wrong tool
It does not tell you whether your code is safe. The README says so, and any process that treats a zero unsafe count as a security property is misreading the output, because unsoundness can live entirely in a dependency you did not write.
It does not tell you where the unsafe code is in a way you can act on. A per dependency count is a ranking for your attention, not a finding. To act on one you would read that dependency's unsafe blocks, which is the slow part the tool does not do.
It does not cover what is not unsafe. Safe abstractions over unsafe internals, unsound safe functions, and logic errors are all invisible to a count. The README's own framing, statistical input to auditing, is the honest description of the output.
It also does not tell you much about feature flags, target specific code or build configuration, since the README does not document any of that and the test crates focus on dependency graph shapes rather than feature resolution.
The realistic workflow is one run before an audit to find which dependencies deserve the time, then an actual reading of the code. Used any other way, the number is decoration.
Editorial conclusion
Adopt cargo-geiger when you want a dependency wide picture of unsafe code before an audit, since running it once across a lockfile answers a question that reading your own source cannot. Do not adopt it as a compliance gate, because the README states explicitly that the tool does not advise whether code is truly insecure, and a crate with zero unsafe functions can still be unsound through a dependency. Before wiring it into anything, run it on a small crate with known dependencies to see the output format you would be parsing, and pin the version, since v0.14.0 is recent and the exposed library APIs are described as unversioned and highly unstable.
Frequently asked questions
How do I install cargo-geiger?
Run cargo install --locked cargo-geiger to use a system installed OpenSSL, or cargo install --locked cargo-geiger --features vendored-openssl to build and statically link OpenSSL. Pre-built binaries are also published on the GitHub releases page.
Does cargo-geiger say whether code is insecure?
No. The README states the tool is not meant to advise directly whether the code is truly insecure, and that its purpose is to provide statistical input to auditing, for example alongside cargo-crev or safety-dance.
How do I run cargo-geiger on a project?
Navigate to the directory containing the Cargo.toml you want to analyze and run cargo geiger.
Can I use cargo-geiger as a library?
Three libraries are exposed: cargo-geiger, which the README describes as unversioned and highly unstable with any function subject to change, cargo-geiger-serde for the serializable report types, and geiger for the decoupled cargo components.
Where should I report a bug in cargo-geiger?
The README links to the issue tracker at the rust-secure-code organisation, while the repository itself now lives at geiger-rs/cargo-geiger. Check the current repository rather than trusting the linked tracker path.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/geiger-rs-cargo-geiger)Star history chart for your README
[](https://hysenlabs.com/projects/geiger-rs-cargo-geiger)Was this useful?