Security advisory for crates.io, 2017-09-19

417 views
Skip to first unread message

Alex Crichton

unread,
Sep 19, 2017, 12:48:59 PM9/19/17
to rustlang-securi...@googlegroups.com
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

# Security advisory for crates.io, 2017-09-19

The Rust team was recently notified of a security vulnerability affecting
crates.io. It has since been resolved, and there is no indication that the bug
has been exploited. No action is necessary from any user, this email is a
notice about the vulnerability in addition to a disclosure of the timeline of
events.

When Cargo extracted the source code for a package on crates.io it could
overwrite the source code for another package.

Source code is stored on crates.io as a tarball, and Cargo uses the `tar` crate
to parse these tarballs and extract them. Historically Cargo extracted these
tarballs directly into the global crate cache [1], relying on each tarball to
only actually have one directory of the form `foo-0.1.0` (`$name-$version`).
This was not verified, however, and if a tarball contained multiple top-level
directories then the extraction would overwrite or create new files in the
global crate cache.

Cargo itself would never manufacture a tarball with more than one top-level
directory, but a malicious tarball could be uploaded directly to crates.io
which could exhibit this behavior. Cargo's cache for downloaded crates is a
global one, which means that an unrelated project could poison anothers'
dependency graph by overwriting a crate's source code, causing malicious code
to be compiled and executed eventually.

A fix for this issue was first implemented on crates.io [2] to reject any
tarball being published which contains a top-level directory not of the form
expected (`$crate_name-$crate_version`). After this patch was merged and
deployed all tarballs ever published to crates.io were downloaded and
inspected. No tarball ever uploaded to crates.io exhibited malicious behavior
with multiple top-level directories.

As a second precaution a change was also landed in Cargo [3] which causes Cargo
to return an error if a tarball looks ill-formed. This change will be present
in Cargo of Rust 1.22.0, to be released 2017-11-23. To reiterate, this change
is not needed to protect from malicious downloads from crates.io. Only
well-formed tarballs can be uploaded to crates.io as of a few days ago.

Many thanks to Justin Geibel (@jtgeibel) for responsibly reporting this [4] and
helping us identify and test a fix! The timeline of events is as follows:

* 2017-09-13 @ 19:19 - Justin sends mail to secu...@rust-lang.org about this
* 2017-09-13 @ 19:28 - response sent to Justin acknowledging the vulnerability
* 2017-09-13 @ 21:14 - a patch to crates.io was finished, all current
tarballs verified not-malicious
* 2017-09-14 @ 9:10 - crates.io PR proposed
* 2017-09-14 @ 10:04 - crates.io PR merged and deployed
* 2017-09-14 @ 12:08 - cargo PR proposed
* 2017-09-14 @ 12:26 - crates.io verified again to contain no malicious tarballs
* 2017-09-17 @ 16:10 - cargo PR merged

[1]: https://github.com/rust-lang/cargo/blob/3d3f2c05d742e5f907e951aa8849b03f0bc1a895/src/cargo/sources/registry/mod.rs#L294-L319
[2]: https://github.com/rust-lang/crates.io/pull/1054
[3]: https://github.com/rust-lang/cargo/pull/4493
[4]: https://www.rust-lang.org/en-US/security.html
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1

iQIcBAEBAgAGBQJZwUlpAAoJEO+5hgrnUg2s0ckP/37wu3fmg2Dt05U6eVsuw93n
L97BVkqSccnLlvCis5I0PyeP/Yax9VYGS+vDNiAh/jX5K7utXJM+psIktxfAlFub
EhUkwk6Qz3crUBsqSREqKqVqyfnUVNYZ8bq1G4CJ35578qXIOKymn/MTZ+9UhmmZ
/tDAQA7MiEpmYHAAATDj6ixxI7lVC1V15ojX7jKKMjoikwojEIsFhGMEuQQ9CJyh
jPY9jBST79ooVe34PuHeeVT5xFhXThR08yylBhMpUGqhy0ghPLw90OUuNsZNzlkL
IDG3GIucR4i/0YlEO3l5QIJkKRTAM8IaCZbNiAdRSMpavnSVBwnuPXnr03gbw2Ru
F7wFOND56YGxAOKuwedBOWj3UhIeMHk6QZmDWEBtIIRoD4b00P14RVDLvp0wmjFP
MnJNapBrcFixxYPHSX9GTp7Bsjd0knVwQSQg8V+VMxgnzmpn7y9vMUos2ku5whld
Yzmy+IKkTfqFaUYuA3z+59TCjELkfQ4cuSjVrcPP9Hg+4tdNUsETzCzRV852YaKX
wl0NY/pWVohLpH4a43yjVEUdnQiDFEIG3Sot+aL+h8Sedih8DkcVq8hXXe0NvcfY
I+9ArnXRHsR0nWPToL2pKjWHeON2o0DN2mRu1kaY6Aqv6HLeB5QV4AOFX8OkkBOE
4rBjcAFR8CGT/nuF0tr8
=32Wn
-----END PGP SIGNATURE-----
Reply all
Reply to author
Forward
0 new messages