Backdooring Rust crates for fun and profit

This page summarizes the projects mentioned and recommended in the original post on news.ycombinator.com

Our great sponsors
  • InfluxDB - Power Real-Time Data Analytics at Scale
  • WorkOS - The modern identity platform for B2B SaaS
  • SaaSHub - Software Alternatives and Reviews
  • cargo-crev

    A cryptographically verifiable code review system for the cargo (Rust) package manager.

  • Cargo-crev's writ seems to be much more expansive and nebulous than security:

    https://github.com/crev-dev/cargo-crev/wiki/Howto:-Create-Re...

    > While it's still open for debate, the current opinion is that additional fields are not useful for the downstream users. Instead they just complicate their life, putting the burden of the decision from the reviewer onto them. At the end, a downstream user of a review just wants to know: "is it OK to use this package or not?". Your role as a reviewer is to provide that judgment.

    That irks me. I don't care about popularity contests, I only care whether a crate is malicious or not. If it has security vulnerabilities, I can deal. But if downloading and running a proc macro crate build runs gives an attacker RCE, that's altogether different.

  • stb

    stb single-file public domain libraries for C/C++

  • C relies vastly on dynamic linking. C++ cannot dynamically link templates, so it's pretty common for a C++ library to be made entirely of header files.

    Also, that's really only true of a small number of Linux and BSD flavors. Applications shipped on Windows, macOS, Android, iOS, or any of the Linux "application bundle" systems like the Steam runtime, Docker, FlatPak, will deliberately avoid using globally-specified dependencies.

    It's also commonplace to avoid declaring dependencies in C by vendoring them, like how VLC basically includes its own implementation of a bunch of data structures [1], and the entire universe of single-file libraries [2].

    [1]: https://wiki.alopex.li/LetsBeRealAboutDependencies#gotta-go-...

    [2]: https://github.com/nothings/stb/blob/master/docs/stb_howto.t...

  • InfluxDB

    Power Real-Time Data Analytics at Scale. Get real-time insights from all types of time series data with InfluxDB. Ingest, query, and analyze billions of data points in real-time with unbounded cardinality.

    InfluxDB logo
  • pub-dev

    The pub.dev website

  • Yes, they do that in Dart's pub [1].

    They also have the concept of verified publishers[2], which is pretty neat (similar to Maven Central), and keep track of a score for each package (e.g. https://pub.dev/packages/darq/score) including up-to-date dependencies and result of static analysis.

    Dart is doing a lot of things right.

    [1] https://pub.dev/

    [2] https://dart.dev/tools/pub/publishing#verified-publisher

  • docs.rs

    crates.io documentation generator

  • > While it’s possible to audit the code of a crate on https://docs.rs on clicking on a [src] button, it turns that I couldn’t find a way to inspect build.rs files. Thus, combined with a malicious update, it’s the almost perfect backdoor.

    Docs.rs has its own source view on /crate that's separate from rustdoc's. For example, you can see the build.rs for boring-sys on `https://docs.rs/crate/boring-sys/1.1.1/source/build.rs`.

  • slsa

    Supply-chain Levels for Software Artifacts

  • Sigstore & Cosign are worth looking into as well. GoReleaser supports those for compiled binaries.

    SLSA is another

    https://sigstore.dev/

    https://slsa.dev/

  • rekor

    Software Supply Chain Transparency Log

  • Sigstore & Cosign are worth looking into as well. GoReleaser supports those for compiled binaries.

    SLSA is another

    https://sigstore.dev/

    https://slsa.dev/

  • cargo-dephell

    Cargo dephell analyzes the third-party dependencies of a Rust workspace

  • That's why I started https://github.com/mimoo/cargo-dephell and https://github.com/diem/whackadep btw, to try to get a sense of the risk in our Rust dependencies. The second one is a web UI that can update periodically and shows you what's up with your dependencies. If there's a new update, it'll tell you if it affected a `build.rs` file (which triggers a warning). I wanted to add more rules, like the ones mentioned in the article, but never had the time to do it.

  • WorkOS

    The modern identity platform for B2B SaaS. The APIs are flexible and easy-to-use, supporting authentication, user identity, and complex enterprise features like SSO and SCIM provisioning.

    WorkOS logo
  • whackadep

    Managing Rust dependencies via a dashboard

  • That's why I started https://github.com/mimoo/cargo-dephell and https://github.com/diem/whackadep btw, to try to get a sense of the risk in our Rust dependencies. The second one is a web UI that can update periodically and shows you what's up with your dependencies. If there's a new update, it'll tell you if it affected a `build.rs` file (which triggers a warning). I wanted to add more rules, like the ones mentioned in the article, but never had the time to do it.

  • Cargo

    The Rust package manager

  • I love Rust, but it's particularly frustrating to me how it (nearly) forces you to use a single centralized package repository. Shameless plug for an issue: https://github.com/rust-lang/cargo/issues/10045

    I don't have a gripe with crates.io per se, but that the tooling doesn't work offline and works poorly without crates.io is a real problem.

  • cargo-geiger

    Detects usage of unsafe Rust in a Rust crate and its dependencies.

  • Exactly. And raising awareness of use of these less-than-palatable practices tends to lead to a constant pressure to only use them when strictly necessary, leading things to a broadly safer end state. cargo-geiger is a nice example of people building things "around" the system, but I really think it needs to be first-class and visible everywhere to have an ecosystem-wide impact: https://crates.io/crates/cargo-geiger

  • glog

    Leveled execution logs for Go (by golang)

  • By globals, I mean global resources outside of the codes namespace. It may not even be a resource in the process, such as a log file or temporary directory or a database. If you have two versions of a crate in their completely separate worlds, and call both of their init_logging() functions to log to a file specified by an environment variable, things are likely to go pear shaped when they stomp over each others log file.

    I'm a Rust novice, but the example I tripped over in Go was https://github.com/golang/glog. It has a module level init() initialization routine that makes calls to the stdlib flags package, manipulating the default command line flags (a global resource). If you ended up with multiple versions of glog via transient dependencies, your program would panic on startup as the second version's init() would make calls only allowed to be called once. Rust thankfully avoids this particular one by requiring initialization to be called by main() (apart from the hack described in the article).

NOTE: The number of mentions on this list indicates mentions on common posts plus user suggested alternatives. Hence, a higher number means a more popular project.

Suggest a related project

Related posts