CVE-2026-5222: avoid stripping .git suffix when for non git registries
authorArlo Siemsen <arkixml@gmail.com>
Mon, 25 May 2026 07:49:43 +0000 (09:49 +0200)
committerFabian Grünbichler <debian@fabian.gruenbichler.email>
Thu, 28 May 2026 18:58:07 +0000 (20:58 +0200)
FG: adapt patches
Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
Gbp-Pq: Topic cargo
Gbp-Pq: Name CVE-2026-5222-avoid-stripping-.git-suffix-when-for-non-gi.patch

src/tools/cargo/src/cargo/sources/git/source.rs
src/tools/cargo/src/cargo/util/canonical_url.rs

index d6dbe03e4c0105a9fda6feb7f59bf05774385463..a7b3205c8305492c1e2184364c0de01f04c9478b 100644 (file)
@@ -470,6 +470,13 @@ mod test {
         assert_eq!(ident1, ident2);
     }
 
+    #[test]
+    fn test_canonicalize_idents_does_not_strip_dot_git_for_sparse() {
+        let ident1 = ident(&src("sparse+https://crates.io/fake-registry"));
+        let ident2 = ident(&src("sparse+https://crates.io/fake-registry.git"));
+        assert_ne!(ident1, ident2);
+    }
+
     fn src(s: &str) -> SourceId {
         SourceId::for_git(&s.into_url().unwrap(), GitReference::DefaultBranch).unwrap()
     }
index 7516e0356913e31fc295996d3c88c568c5e0cfee..2716d2d4f5b265a962bcaf18a8d315715bb161d5 100644 (file)
@@ -33,27 +33,31 @@ impl CanonicalUrl {
             url.path_segments_mut().unwrap().pop_if_empty();
         }
 
-        // For GitHub URLs specifically, just lower-case everything. GitHub
-        // treats both the same, but they hash differently, and we're gonna be
-        // hashing them. This wants a more general solution, and also we're
-        // almost certainly not using the same case conversion rules that GitHub
-        // does. (See issue #84)
-        if url.host_str() == Some("github.com") {
-            url = format!("https{}", &url[url::Position::AfterScheme..])
-                .parse()
-                .unwrap();
-            let path = url.path().to_lowercase();
-            url.set_path(&path);
-        }
+        // Perform further canonicalization specific to git registries, which
+        // do not contain a `+` specifier.
+        if !url.scheme().contains('+') {
+            // For GitHub URLs specifically, just lower-case everything. GitHub
+            // treats both the same, but they hash differently, and we're gonna be
+            // hashing them. This wants a more general solution, and also we're
+            // almost certainly not using the same case conversion rules that GitHub
+            // does. (See issue #84)
+            if url.host_str() == Some("github.com") {
+                url = format!("https{}", &url[url::Position::AfterScheme..])
+                    .parse()
+                    .unwrap();
+                let path = url.path().to_lowercase();
+                url.set_path(&path);
+            }
 
-        // Repos can generally be accessed with or without `.git` extension.
-        let needs_chopping = url.path().ends_with(".git");
-        if needs_chopping {
-            let last = {
-                let last = url.path_segments().unwrap().next_back().unwrap();
-                last[..last.len() - 4].to_owned()
-            };
-            url.path_segments_mut().unwrap().pop().push(&last);
+            // Repos can generally be accessed with or without `.git` extension.
+            let needs_chopping = url.path().ends_with(".git");
+            if needs_chopping {
+                let last = {
+                    let last = url.path_segments().unwrap().next_back().unwrap();
+                    last[..last.len() - 4].to_owned()
+                };
+                url.path_segments_mut().unwrap().pop().push(&last);
+            }
         }
 
         Ok(CanonicalUrl(url))