Issues involving reporting a security vulnerability in cargo usually start by following the Rust security policy. The Security Response Working Group (“the WG”) is responsible for running the process of handling the response to a security issue. Their process is documented at Handling Reports. This document gives an overview of the process from a Cargo team member's perspective.
The general order of events happens as follows:
The “reporter” (even if it is a Cargo team member) reports an issue to security@rust-lang.org.
The WG will evaluate if the report is credible, and manages responses to the reporter.
The WG will start a private Zulip stream to coordinate discussion and plans for a fix.
The WG will pull in one or more team members into the Zulip stream (“responders”).
A discussion then starts to evaluate the severity of the issue and what possible solutions should be considered. This includes figuring out who will volunteer to actually develop the patches to resolve the issue, and who will review it.
The WG will create a temporary private fork of the rust-lang/cargo repo using GitHub's repository security advisory system. This provides a space where changes can be securely posted, and the security advisory can be drafted. See “Collaborating in a temporary private fork” for some screenshots of what this looks like. GitHub includes instructions on how to work with the fork.
Beware that the private fork has some limitations, such as not supporting CI, or (for some weird reason) not supporting syntax highlighting.
Someone will need to review the patches and make sure everyone agrees on the solution. This may also involve the WG conferring with the reporter to validate the fix.
Create a rollout plan. This includes deciding if there will be a new patch release of Rust, or if it should wait for the next stable release, or whether to remove the embargo on the fix.
The WG will handle drafting a Security Advisory using GitHub's Security Advisory (“GHSA”) system. GHSA-r5w3-xm58-jv6j is an example of what this looks like. This process also involves reserving a CVE number, where the report will eventually be posted.
The responders should carefully review the report to make sure it is correct.
This process may also involve deciding on the CVSS score. There are a bunch of calculators on the web where you can see how this works (such as the FIRST CVSS Calculator, or you can view GitHub's calculator by drafting a security advisory in one of your personal repos). FIRST has a user guide for deciding how to score each characteristic.
If it is decided to do a patch release of Rust, the general overview of steps is:
rust-lang/rust to prepare the point release. This usually includes changes for stable, beta, and nightly.rust-lang/rust to incorporate the fix and prepare a new release.Sometimes it may be necessary to make changes to external dependencies to support a fix. This can make things complicated. If the change is by itself benign and not directly related to the security issue, then it may be safe to publicly propose the change (but not giving context) and try to get a new release of the dependency made (though confer with the WG first!). However, if the issue is directly related to the dependency, then it becomes significantly more awkward.
The general process for GHSA-r5w3-xm58-jv6j which involved a fix in git2-rs was handled by the responders because it is a dependency owned by the rust-lang org. The general outline of how we managed this is:
rust-lang/git2-rs just like we did for rust-lang/cargo. git2-rs also had its own Security Advisory just like cargo did.rust-lang/cargo private fork had to have a temporary [patch] git dependency on the git2-rs private fork.[patch], and pretend as-if git2-rs had already been published.Cargo.lock to pick up the new git2 dependencies.If the change is in a crate not managed by any responder, then confer with the WG on a strategy. One option is to create a temporary fork used for the security response that will be removed as soon as the security advisory is released and a new public release of the dependency is made with the fix.
There are a lot of details to handle, and it can be a bit of a challenge under time pressure. The following is a checklist of some items to pay attention to during the process.
Pre-release:
Cargo.toml is updated correctly on the stable branch private PR.Cargo.lock is updated (stable, beta, master branches).CHANGELOG.md on cargo's master branch private PR.RELEASES.md on rust's master branch private PR (and stable and beta?).[patch] table.Showtime:
Cargo.lock.rust-lang/cargo get updated.rust-lang/rust get updated, pointing to the correct submodule versions.Post release:
rust-lang/cargo got a new tag.rust-lang/cargo repository (stable, beta, and master).rust-lang/rust repository (stable, beta, and master).