cargo: Fix CVE-2026-5223

This patch applies the upstream fix as referenced in [2], using the commit shown in [1].

[1] 285cebf589
[2] https://security-tracker.debian.org/tracker/CVE-2026-5223

(From OE-Core rev: 9a7fa66844042347a01347538c221115eb40856b)

Signed-off-by: Anil Dongare <adongare@cisco.com>
Signed-off-by: Yoann Congal <yoann.congal@smile.fr>
Signed-off-by: Paul Barker <paul@pbarker.dev>
This commit is contained in:
Anil Dongare
2026-06-15 06:00:42 -07:00
committed by Paul Barker
parent ae2f076ef7
commit 7aad94e82e
2 changed files with 115 additions and 0 deletions

View File

@@ -0,0 +1,114 @@
From 285cebf58911eca5b7f177f5d0b1c53e1f646577 Mon Sep 17 00:00:00 2001
From: Josh Triplett <josh@joshtriplett.org>
Date: Mon, 30 Mar 2026 10:35:55 -0700
Subject: [PATCH] CVE-2026-5223: prohibit unpacking symlinks and other
unexpected entries
Cargo has historically not allowed creating .crate packages containing
symlinks. (It packages the symlink target in place of the symlink,
instead.) So, any package containing a symlink would have to be
hand-constructed. Such packages are also not allowed on crates.io, so it
could only come from an alternate registry.
Rather than dealing with symlink traversal attacks when unpacking a
crate, just prohibit symlinks entirely.
In the process, also prohibit other kinds of unusual entries. As an
exception, allow character devices but warn about them, because some
exist in crates on crates.io.
CVE: CVE-2026-5223
Upstream-Status: Backport [https://github.com/rust-lang/cargo/commit/285cebf58911eca5b7f177f5d0b1c53e1f646577]
Backport Changes:
- Adapted to Cargo 0.76.0 in Rust 1.75.0, where unpack_package() still carries
the extraction loop directly and the newer smuggled-symlink regression test
is not present.
(cherry picked from commit 285cebf58911eca5b7f177f5d0b1c53e1f646577)
Signed-off-by: Anil Dongare <adongare@cisco.com>
---
src/tools/cargo/src/cargo/sources/registry/mod.rs | 9 ++++++++-
src/tools/cargo/tests/testsuite/registry.rs | 31 ++++++++++++-----------
2 files changed, 24 insertions(+), 16 deletions(-)
diff --git a/src/tools/cargo/src/cargo/sources/registry/mod.rs b/src/tools/cargo/src/cargo/sources/registry/mod.rs
index 7ee461e..c97d96d 100644
--- a/src/tools/cargo/src/cargo/sources/registry/mod.rs
+++ b/src/tools/cargo/src/cargo/sources/registry/mod.rs
@@ -197,7 +197,7 @@ use cargo_util::paths::{self, exclude_from_backups_and_indexing};
use flate2::read::GzDecoder;
use serde::Deserialize;
use serde::Serialize;
-use tar::Archive;
+use tar::{Archive, EntryType};
use tracing::debug;
use crate::core::dependency::Dependency;
@@ -636,6 +636,13 @@ impl<'cfg> RegistrySource<'cfg> {
prefix
)
}
+ // Prevent unpacking symlinks and other unexpected entry types.
+ match entry.header().entry_type() {
+ EntryType::Regular | EntryType::Directory => {}
+ t => anyhow::bail!(
+ "invalid tarball downloaded, contains an entry at {entry_path:?} with invalid type {t:?}",
+ ),
+ }
// Prevent unpacking the lockfile from the crate itself.
if entry_path
.file_name()
diff --git a/src/tools/cargo/tests/testsuite/registry.rs b/src/tools/cargo/tests/testsuite/registry.rs
index b5dff27..178bfff 100644
--- a/src/tools/cargo/tests/testsuite/registry.rs
+++ b/src/tools/cargo/tests/testsuite/registry.rs
@@ -2550,8 +2550,7 @@ fn package_lock_inside_package_is_overwritten() {
}
#[cargo_test]
-fn package_lock_as_a_symlink_inside_package_is_overwritten() {
- let registry = registry::init();
+fn package_lock_as_a_symlink_inside_package_is_invalid() {
let p = project()
.file(
"Cargo.toml",
@@ -2573,21 +2572,23 @@ fn package_lock_as_a_symlink_inside_package_is_overwritten() {
.symlink(".cargo-ok", "src/lib.rs")
.publish();
- p.cargo("check").run();
+ p.cargo("check")
+ .with_status(101)
+ .with_stderr_data(str![[r#"
+[UPDATING] `dummy-registry` index
+[LOCKING] 1 package to latest compatible version
+[DOWNLOADING] crates ...
+[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`)
+[ERROR] failed to download replaced source registry `crates-io`
- let id = SourceId::for_registry(registry.index_url()).unwrap();
- let hash = cargo::util::hex::short_hash(&id);
- let pkg_root = cargo_home()
- .join("registry")
- .join("src")
- .join(format!("-{}", hash))
- .join("bar-0.0.1");
- let ok = pkg_root.join(".cargo-ok");
- let librs = pkg_root.join("src/lib.rs");
+Caused by:
+ failed to unpack package `bar v0.0.1 (registry `dummy-registry`)`
- // Is correctly overwritten and doesn't affect the file linked to
- assert_eq!(ok.metadata().unwrap().len(), 7);
- assert_eq!(fs::read_to_string(librs).unwrap(), "pub fn f() {}");
+Caused by:
+ invalid tarball downloaded, contains an entry at "bar-0.0.1/.cargo-ok" with invalid type Symlink
+
+"#]])
+ .run();
}
#[cargo_test]
--
2.44.4

View File

@@ -14,6 +14,7 @@ SRC_URI += "https://static.rust-lang.org/dist/rustc-${RUST_VERSION}-src.tar.xz;n
file://repro-issue-fix-with-v175.patch;patchdir=${RUSTSRC} \
file://0001-cargo-do-not-write-host-information-into-compilation.patch;patchdir=${RUSTSRC} \
file://CVE-2026-5222.patch;patchdir=${RUSTSRC} \
file://CVE-2026-5223.patch;patchdir=${RUSTSRC} \
"
SRC_URI[rust.sha256sum] = "4526f786d673e4859ff2afa0bab2ba13c918b796519a25c1acce06dba9542340"