Idea: Security advisories as part of crates.io metadata

For a decently-sized application it’s not uncommon to indirectly depend on more than hundred crates. Running grep -c package Cargo.lock on my rather small webapp yields a count of 151, for example. Most of those crates are indirect dependencies, and I suspect that this amount of dependencies, plus the common practice of version pinning, may slow the propagation of security updates down to the point where it becomes a problem endemic to the ecosystem. Here’s an example.

Assume that my application W depends on crate X, which depends on crate Y, which depends on crate Z. All crates are post-1.0 and pinned by MINOR version from the previous crate.

If a security issue is disclosed to the author of crate Z, they need to decide whether to backport the patch to the last n minor versions:

  • If they do, a simple cargo update for my application W will suffice to recieve the update.
  • If they don’t, I need to wait for the maintainers of crate X and Y to update their Cargo.tomls.

Unfortunately I’m depending on open source libraries where nobody gets paid for their work. This means that the maintainer of Z is less likely to backport the patch to other MINOR versions, only the latest version gets a PATCH release. The maintainers of X and Y are less likely to update their dependencies either, because they do all of this in their freetime as well. This is a social problem though, and people are just getting started writing about this issue.

Assuming there will be no backports for this patch, a thing the author of Z could do in this situation is to yank all vulnerable versions of Z. However, this doesn’t actually prevent anybody from compiling existing applications with this vulnerable dependency, but at least it prevents writing new ones. But even there it is not an entirely correct thing to do, as even a critical security issue may affect only small parts of the crate’s public API.

Instead I’m proposing a “soft-core” version of the yank command, let’s call it defame. It is essentially CVEs, but integrated into the package index.

  • It would mark (by default) all existing versions on crates.io of the given crate as insecure, perhaps with the possibility to attach text that describes the vulnerability in detail.
  • Cargo would refuse to compile such versions without an override switch. This override switch could be defined in the Cargo.toml of any crate that depends on it (directly or indirectly).

With those annotations, one could e.g. build tooling that automatically notifies me, the application developer, about security issues in my dependencies.

Comments?

3 Likes

This sounds like a loud version of yanking to me. Probably we should think more about multiple levels of yanking or in general discouraging the use of certain versions of the crate.

1 Like

Reminds me of the npm deprecate command, which will warn you whenever an npm install includes a version that was deprecated, along with an optional message.

2 Likes

It is similar, but for security advisories, “deprecate” sounds like a very weak term as it may be applied to all older versions, whether they have security issues or not. The main difference for me is in the way Cargo would behave if it encountered such a package.

In the abstract, I like the idea. I’ve had a similar idea, myself. That said, I’d vote for denounce over defame; it needs to sound suitably weighty.

I’ve read in the past some grumbling from people about distros and projects that don’t use CVE numbers to track vulnerabilities, so perhaps that could also be integrated.

Finally, one thing I’d like to see with this is some kind of mechanism for actively warning developers that a particular project may need to be recompiled due to upstream problems. One way might be to find all transitive reverse dependencies of a denounced crate which have one or more binary targets. The owners can then be warned, perhaps via some combination of RSS, auto GitHub issue, or a periodic automatic check on the part of Cargo.

Another idea might be some kind of schedulable, local cargo check-denounced that recursively crawls project directories, looking for projects impacted by denounced crates (for things that use crates.io, but aren’t published there).

This should also probably have input from packagers, if it starts to pick up steam.

That said, I'd vote for denounce over defame; it needs to sound suitably weighty.

Fair enough, I'm not a native speaker.

CVE numbers to track vulnerabilities, so perhaps that could also be integrated.

Yes, although I think one has to ask for a CVE number on a mailinglist if I recall correctly. Flooding that with automated requests may be counterproductive.

Finally, one thing I'd like to see with this is some kind of mechanism for actively warning developers that a particular project may need to be recompiled due to upstream problems.

I'd like to see a Rust version of https://greenkeeper.io/. In essence it automatically opens pull requests to update NPM dependencies. I think such a service could be even more powerful with the additional metadata I propose, as it could then also file issues if a direct/indirect dependency has a security announcement.

What crates.io could do out of the box is to email crate owners if their dependencies have security issues, since it requires no set up steps by the crate developer. This is a useful default IMO, but could be opt-out.

I think integrating a true vulnerability tracking system into crates.io is a fantastic idea. I’ve seen systems like this done out-of-band, such as the Ruby Advisory Database and the corresponding bundler-audit tool, and also work professionally with systems which use this data to automatically track active vulnerabilities on deployed tools, so perhaps I’m a bit biased.

I think perhaps people are getting a bit too hung up on the name. I’d say if you really want it to function as a vulnerability tracking system, you should call a spade a spade and just name it vuln. Ideally I think it would tie in with systems like CVE and DWF. cargo can then warn (or optionally fail) if you are locked to vulnerable packages.

I could see this same functionality being implemented using an out-of-band database and some sort of cargo plugin too… provided there isn’t interest in getting it into crates.io and cargo proper.

Perhaps open an issue on the crates.io issue tracker on GitHub?

I think I agree with you about the naming. I was assuming that there'd be other reasons unrelated to security why one would annotate their package like that, but I currently can't think of one.

I suggest that cargo vuln should also guide the user through requesting a CVE number.

Unsure what's the best issue tracker, but since this forum is used for pre-RFCs as well I thought it'd be better to post here first.

It is similar, but for security advisories, “deprecation” sounds like a too weak term IMO and may be applied to all outdated versions, with or without security issues.

The main difference for me is in the way Cargo behaves if it encounters such a version.

FWIW I filed an issue at https://github.com/rust-lang/crates.io/issues/406

I have the work-in-progress of an RFC at https://github.com/untitaker/rfcs/blob/security-advisories/text/0000-security-advisories.md. The last three sections are not written yet, so I’ll not file a PR yet.

This is a crosspost from the crates.io issue. I’m not sure which forum is appropriate.

  • I consider Summary, Motivation and Detailed Design to be complete for my standards, but I haven’t given much thought to it yet. I don’t think it has to be described how the Crates.io API should look, but I considered specifying the UX for this important. Unsure about the way I specified it though.
  • Drawbacks: Danger of duplicating CVEs maybe?
  • Alternatives: List similar concepts in other ecosystems: Ruby Advisory Database, npm deprecate, and why this command is specifically for vulnerabilities. Do I have to rationalize every UX decision?
  • Unresolved questions:
    • How tooling around this API should look like.
      • Should crates.io notify authors of reverse dependencies per email (scraped from GitHub)?
      • Should there be an RSS feed? (IMO no, as RSS is not a reliable notification system for technical reasons: If RSS reader updates seldomly, items may be missed).
      • How do we expose this API to third-party developers? Ideally they should not need to install cargo to use the API.

In https://github.com/rust-lang/cargo/issues/2608, @alexcrichton described an idea to allow people to pull their own packages and give a reason – then, if cargo was building and found a yanked crate in your dependencies, it would warn you that a cargo update is a good idea. Seems like a very similar thing.

1 Like

Here are some reasons I think yanked packages (as they are right now) are not a solution for security vulnerabilities:

  • Cargo doesn’t allow yanked packages to be used in new packages. I think people who know what they’re doing should be allowed to depend on vulnerable packages, they might use the crate in a way that poses no security problem.

  • Cargo doesn’t give any advice about further procedure when yanking a package. I think in the context of security vulnerabilities this is very much needed, as few OSS maintainers are exposed to this problem regularly enough to know what they’re doing.

  • Lastly, the data exposed via the Crates.io would be a lot less structured. Automatic notification like I imagine with this draft would be impossible because the overwhelming majority of yanks are for relatively uncritical things.

All of these things may of course be fixable by changing the semantics of yank accordingly: We could require people to “categorize” their yanks into security, deprecation, and whatever else comes to mind. Then, when attempting to compile such crates, Cargo could exhibit different behavior, being less “stern” when trying to compile a deprecated version, and more “stern” when compiling a version with security vulnerabilities. It could also display better advice depending on the category (such as “request a CVE for this”) and the data would obviously be more structured as well.

I like the idea of notifying users that they're depending on an insecure library version very much, but the above suggested approach is not the way to do it. Thou shal never break another project's build. EVER. Any idea that proposes this should be dead in the water.

Printing a warning during the build sounds fine though.

This section is already revised in the linked RFC draft. It now prints a warning when compiling, and cargo test fails instead.

3 Likes

I want to add my two cents to this: I agree that using yank for this is not the best idea. It just does not have enough meta information. It would be great if you could get an overview of the sanity of your app and ideally that spits out why exact something is a security problem. In particular large packages often contain security issues in areas that are unused so you might want to just explicitly silence a particular security issue after review.

Ideally when you mark a package to have a security issue you assign CVE numbers or a local identifier which can be explicitly silenced so if something else shows up in the future you get a warning again.

Good idea about assigning a identifier. Having CVE numbers as those would make using CVEs mandatory. For some reason I wanted to avoid that, but I’m not sure why.

We can totally “overload” yank to work with security stuff, the question is whether this is shoehorning too much logic into one command.

Actually the more I think about it, the more I prefer:

  • adding both a freeform “reason” field and a category (security|deprecated|other) to yanked versions
  • allowing overrides of some form to compile yanked versions even in a new application.
  • printing warnings for existing applications

Thoughts?

I don’t think one could make CVEs mandatory. They just recently started issuing longer numbers. Pretty sure they would not appreciate if one starts to simplify the process so that they have to issue a few orders of magnitude more. Crates could assign local numbers.

Extending yanking to be more descriptive of why it was yanked, and printing out warnings when using yanked crates, sounds like a good idea to me.

2 Likes