diff --git a/crates/crates_io_tarball/src/manifest.rs b/crates/crates_io_tarball/src/manifest.rs index 1e0662074d2..0d94f521995 100644 --- a/crates/crates_io_tarball/src/manifest.rs +++ b/crates/crates_io_tarball/src/manifest.rs @@ -7,6 +7,13 @@ pub fn validate_manifest(manifest: &Manifest) -> Result<(), Error> { // does not accept workspace manifests. let package = package.ok_or(Error::Other("missing field `package`".to_string()))?; + // We don't want to allow [patch] sections in manifests at all. + if matches!(&manifest.patch, Some(patch) if !patch.is_empty()) { + return Err(Error::Other( + "crates cannot be published with `[patch]` tables".to_string(), + )); + } + validate_package(package)?; // These checks ensure that dependency workspace inheritance has been diff --git a/src/tests/krate/publish/dependencies.rs b/src/tests/krate/publish/dependencies.rs index cc6682a4342..2854c0ce6c4 100644 --- a/src/tests/krate/publish/dependencies.rs +++ b/src/tests/krate/publish/dependencies.rs @@ -285,6 +285,38 @@ async fn new_krate_with_wildcard_dependency() { assert_that!(app.stored_files().await, empty()); } +#[tokio::test(flavor = "multi_thread")] +async fn new_krate_with_patch() { + let (app, _, user, token) = TestApp::full().with_token().await; + let mut conn = app.db_conn().await; + + // Insert a crate directly into the database so that new_wild can depend on it + CrateBuilder::new("foo_patch", user.as_model().id) + .expect_build(&mut conn) + .await; + + let manifest = r#" + [package] + name = "new_patch" + version = "1.0.0" + description = "foo?!" + license = "MIT" + + [dependencies] + foo_patch = "1.0.0" + + [patch.crates-io] + foo_patch = { git = "https://github.com/foo/patch.git" } + "#; + + let crate_to_publish = PublishBuilder::new("new_patch", "1.0.0").custom_manifest(manifest); + + let response = token.publish_crate(crate_to_publish).await; + assert_eq!(response.status(), StatusCode::BAD_REQUEST); + assert_snapshot!(response.text(), @r###"{"errors":[{"detail":"failed to parse `Cargo.toml` manifest file\n\ncrates cannot be published with `[patch]` tables"}]}"###); + assert_that!(app.stored_files().await, empty()); +} + #[tokio::test(flavor = "multi_thread")] async fn new_krate_dependency_missing() { let (app, _, _, token) = TestApp::full().with_token().await;