diff --git a/crates/crates-io/lib.rs b/crates/crates-io/lib.rs index 0e48b1ca5adf..ce14c80acecc 100644 --- a/crates/crates-io/lib.rs +++ b/crates/crates-io/lib.rs @@ -394,6 +394,9 @@ impl Registry { Some(s) => s, None => bail!("no upload token found, please run `cargo login`"), }; + if self.host_is_crates_io() && token.chars().any(|c| !c.is_alphanumeric()) { + bail!("malformed token: Token must be alphanumeric"); + } headers.append(&format!("Authorization: {}", token))?; } self.handle.http_headers(headers)?; diff --git a/src/cargo/ops/registry.rs b/src/cargo/ops/registry.rs index c1684d0ef316..19b45b7bed1b 100644 --- a/src/cargo/ops/registry.rs +++ b/src/cargo/ops/registry.rs @@ -898,6 +898,9 @@ pub fn registry_login( if tok.is_empty() { bail!("please provide a non-empty token"); } + if source_ids.original.is_crates_io() && tok.chars().any(|c| !c.is_alphanumeric()) { + bail!("malformed token: Token must be alphanumeric"); + } } } if ®_cfg == &new_token { diff --git a/tests/testsuite/login.rs b/tests/testsuite/login.rs index 2a7fdbff2a80..c03b2d21c637 100644 --- a/tests/testsuite/login.rs +++ b/tests/testsuite/login.rs @@ -128,6 +128,39 @@ fn empty_login_token() { .run(); } +#[cargo_test] +fn malformed_login_token() { + let registry = RegistryBuilder::new() + .no_configure_registry() + .no_configure_token() + .build(); + setup_new_credentials(); + + cargo_process("login") + .replace_crates_io(registry.index_url()) + .with_stdout("please paste the token found on [..]/me below") + .with_stdin("😄;>!\t\n") + .with_stderr( + "\ +[UPDATING] crates.io index +[ERROR] malformed token: Token must be alphanumeric +", + ) + .with_status(101) + .run(); + + cargo_process("login") + .replace_crates_io(registry.index_url()) + .arg("") + .with_stderr( + "\ +[ERROR] please provide a non-empty token +", + ) + .with_status(101) + .run(); +} + #[cargo_test] fn bad_asymmetric_token_args() { // These cases are kept brief as the implementation is covered by clap, so this is only smoke testing that we have clap configured correctly.