Skip to content

[rust] Prevent path traversal in tar and pkg extraction#17668

Open
bonigarcia wants to merge 1 commit into
trunkfrom
sm_security_path_traversal_fix
Open

[rust] Prevent path traversal in tar and pkg extraction#17668
bonigarcia wants to merge 1 commit into
trunkfrom
sm_security_path_traversal_fix

Conversation

@bonigarcia

Copy link
Copy Markdown
Member

🔗 Related Issues

NA

💥 What does this PR do?

Add validation to reject archive entries containing ParentDir(..) components in uncompress_tar() and uncompress_pkg(). This prevents malicious archives from writing files outside the intended extraction directory.

The shared validation logic is refactored into check_path_traversal() to avoid duplication (DRY principle).

  • CVE-2025-XXXX: Path Traversal via uncompress_tar
  • CVE-2025-YYYY: Path Traversal via uncompress_pkg

🔧 Implementation Notes

🤖 AI assistance

  • No substantial AI assistance used
  • AI assisted (complete below)
    • Tool(s): OpenCode
    • What was generated:
    • I reviewed all AI output and can explain the change

💡 Additional Considerations

🔄 Types of changes

  • Bug fix (backwards compatible)

@qodo-code-review

qodo-code-review Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (5) 📘 Rule violations (3)

Grey Divider


Action required

1. PKG empty name accepted 🐞 Bug ≡ Correctness
Description
uncompress_pkg() validates ../absolute/prefixed paths but does not reject an empty
entry.name(), so target.join("") resolves to the extraction root and fs::write() may
create/overwrite the target path as a file instead of a directory. This can cause extraction
failures or clobber the intended extraction directory when the target path does not yet exist.
Code

rust/src/files.rs[R231-235]

            let name = entry.name();
+            check_path_traversal(Path::new(name))?;
            let mut file = Vec::new();
            cpio_reader.read_to_end(&mut file)?;
            let target_path_buf = target_path.join(name);
Evidence
In uncompress_pkg(), the entry name is validated only via check_path_traversal(Path::new(name)),
but check_path_traversal() only rejects ParentDir/RootDir/Prefix components; an empty path has no
components and passes. The code then builds target_path_buf = target_path.join(name) and writes to
it, so an empty name targets the extraction root itself. By contrast, uncompress_tar() explicitly
rejects empty paths, showing this is an expected safety check in extraction code.

rust/src/files.rs[95-107]
rust/src/files.rs[223-253]
rust/src/files.rs[375-399]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`uncompress_pkg()` calls `check_path_traversal(Path::new(name))`, but `check_path_traversal()` does not reject empty paths. If a CPIO entry name is `""`, then `target_path.join(name)` resolves to `target` itself, and `fs::write(&target_path_buf, file)` may create/overwrite the extraction root path as a file (especially when `target` doesn’t exist yet).

## Issue Context
The tar extraction path already explicitly rejects an empty entry path; pkg/cpio should match that safety behavior.

## Fix Focus Areas
- rust/src/files.rs[223-253]
- rust/src/files.rs[95-107]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Tar first segment always dropped 🐞 Bug ≡ Correctness
Description
uncompress_tar() always does iter().skip(1) on every entry path, so single-component entries (e.g.,
"file.txt") become an empty path and are unpacked to target itself. This can overwrite the
intended extraction directory path with a file or cause extraction failures for tarballs that don't
include a top-level folder.
Code

rust/src/files.rs[R385-389]

        let entry_path: PathBuf = entry_decoder.path()?.iter().skip(1).collect();
+        check_path_traversal(&entry_path)?;
        let entry_target = target.join(entry_path);
        fs::create_dir_all(entry_target.parent().unwrap())?;
        entry_decoder.unpack(entry_target)?;
Evidence
The tar extraction path always drops the first component, then joins the (possibly empty) path onto
target and unpacks. In contrast, the zip extraction path only drops the first component when the
path has more than one component, which avoids producing an empty relative path for flat archives.

rust/src/files.rs[375-390]
rust/src/files.rs[419-432]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`uncompress_tar()` unconditionally strips the first path component (`iter().skip(1)`), which can turn a valid tar entry path with a single component into an empty path. That causes `entry_target` to resolve to the extraction root (`target`) and `unpack()` may write a file at the `target` path or fail when the code expects `target` to be a directory.

### Issue Context
`unzip()` already has logic to strip the first component only when the archive paths actually contain a parent folder; tar extraction should behave similarly.

### Fix Focus Areas
- rust/src/files.rs[375-390]
- rust/src/files.rs[419-432]

### Suggested fix
- Mirror the `unzip()` approach:
 - Count components (or otherwise detect whether there is a top-level folder).
 - Only `skip(1)` when there is more than one component.
 - Otherwise, keep the original path.
- Additionally, consider explicitly rejecting an empty `entry_path` for regular-file entries to avoid writing directly to `target`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Tar.gz bypasses validation 🐞 Bug ⛨ Security
Description
check_path_traversal() is never applied to the .gz extraction path: uncompress() dispatches
GZ to untargz(), which calls Archive::unpack() directly without validating archive entry
paths. As a result, tar.gz remains outside the PR’s “reject unsafe entries” behavior, undermining
the stated traversal prevention for tar extraction.
Code

rust/src/files.rs[R95-110]

+pub fn check_path_traversal(entry_path: &Path) -> Result<(), Error> {
+    if entry_path
+        .components()
+        .any(|c| {
+            matches!(
+                c,
+                std::path::Component::ParentDir
+                    | std::path::Component::RootDir
+                    | std::path::Component::Prefix(_)
+            )
+        })
+    {
+        return Err(anyhow!("Unsafe entry (path traversal): {:?}", entry_path));
+    }
+    Ok(())
+}
Evidence
The repo’s main decompression dispatcher sends GZ files to untargz(), but untargz() does not
call the newly added check_path_traversal() and instead performs a direct archive unpack;
therefore tar.gz extraction is not covered by the PR’s new validation behavior.

rust/src/files.rs[95-110]
rust/src/files.rs[149-167]
rust/src/files.rs[360-375]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The PR introduces `check_path_traversal()` and uses it in `uncompress_pkg()` and `uncompress_tar()`, but `.tar.gz` files are extracted via `untargz()` which does not validate entry paths.

### Issue Context
`uncompress()` routes `GZ` to `untargz()`, and `untargz()` uses `tar::Archive::unpack()` without calling `check_path_traversal()` on each entry. This means the security behavior added in this PR is not applied to tar.gz.

### Fix Focus Areas
- rust/src/files.rs[149-167]
- rust/src/files.rs[360-375]

### Suggested fix approach
- Refactor `untargz()` to iterate `archive.entries()?` and, for each entry:
 - read `entry.path()?` (or equivalent),
 - apply `check_path_traversal()` to that path,
 - unpack the entry into the intended destination (e.g., by joining to `parent_path` after validation, or using an unpack-into-directory API if available).
- Optionally add a unit test similar to `uncompress_tar_rejects_path_traversal_entry`, but covering the `.gz` path to prevent regressions.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (3)
4. Tar symlink escape 🐞 Bug ⛨ Security
Description
uncompress_tar() only rejects .. components, then unconditionally calls
entry_decoder.unpack(entry_target), which can create symlinks/hardlinks from the archive. A
malicious tar can first create a symlink inside the target (e.g., link -> /etc) and then write
link/passwd, escaping the extraction directory despite passing the .. check.
Code

rust/src/files.rs[R379-385]

    for entry in archive.entries()? {
        let mut entry_decoder = entry?;
        let entry_path: PathBuf = entry_decoder.path()?.iter().skip(1).collect();
+        check_path_traversal(&entry_path)?;
        let entry_target = target.join(entry_path);
        fs::create_dir_all(entry_target.parent().unwrap())?;
        entry_decoder.unpack(entry_target)?;
Evidence
The repo’s new validator only rejects .. path components, and uncompress_tar() still unpacks
entries directly to the filesystem without checking for link entry types. This enables link-based
escapes that do not require .. components in the entry path.

rust/src/files.rs[95-103]
rust/src/files.rs[371-386]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`uncompress_tar()` currently validates paths only by rejecting `..` components, but then unpacks every tar entry as-is. Tar archives can contain symlinks and hardlinks; extracting them allows later entries to write outside the intended extraction directory by writing through those links.

## Issue Context
- `check_path_traversal()` only checks for `Component::ParentDir` and does not account for link-based escapes.
- `uncompress_tar()` uses `entry_decoder.unpack(entry_target)` without checking the tar entry type or preventing symlink/hardlink creation.

## Fix Focus Areas
- rust/src/files.rs[95-103]
- rust/src/files.rs[371-386]

## What to change
1. In `uncompress_tar()`, inspect each tar entry’s type (via the tar header) before unpacking.
2. Reject (return an error) for symlink and hardlink entry types (and any other non-regular types you don’t explicitly support).
  - If directory entries are expected, allow directories.
  - If only regular files are expected for these tarballs, allow only regular files.
3. (Optional but stronger) Add a defense-in-depth check that the extraction path does not traverse through symlinks already present on disk (walk parent components, using `symlink_metadata`, and fail if any component is a symlink).

## Suggested tests
Add a unit test that builds a tar containing:
- an entry that creates a symlink inside the extraction directory
- a subsequent entry that writes through that symlink
and assert extraction fails (or the escaped path is not written).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Absolute path escape 🐞 Bug ⛨ Security
Description
check_path_traversal() only rejects ParentDir (..) components, so absolute/prefixed entry paths
pass validation. In uncompress_pkg(), an absolute name can cause target_path.join(name) to
ignore target_path and write outside the extraction directory.
Code

rust/src/files.rs[R225-231]

        while let Some(next) = cpio_reader.next() {
            let entry = next?;
            let name = entry.name();
+            check_path_traversal(Path::new(name))?;
            let mut file = Vec::new();
            cpio_reader.read_to_end(&mut file)?;
            let target_path_buf = target_path.join(name);
Evidence
The validator only checks for Component::ParentDir, so it does not reject absolute/prefixed paths.
uncompress_pkg() then uses the raw archive name in target_path.join(name) and writes to that
resulting path, enabling writes outside the intended target when name is absolute/prefixed.

rust/src/files.rs[95-103]
rust/src/files.rs[219-237]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`check_path_traversal()` currently only rejects `..` path components. Absolute paths (Unix `/etc/passwd`) and Windows-style prefixed paths (e.g., `C:\Windows\...`, UNC) can still pass validation and escape the intended extraction root when joined with `target`.

## Issue Context
`uncompress_pkg()` validates `entry.name()` with `check_path_traversal(Path::new(name))` and then writes to `target_path.join(name)`. If `name` is absolute/prefixed, the joined path may resolve outside `target`.

## Fix Focus Areas
- rust/src/files.rs[95-103]
- rust/src/files.rs[219-237]

### Suggested fix
- Update `check_path_traversal()` to reject any non-relative components, not just `ParentDir`, e.g. fail on `Component::RootDir` and `Component::Prefix(_)` as well.
- Optionally add a defensive post-join check in `uncompress_pkg()` (and any similar extraction code): after building the output path, ensure it is not absolute and is lexically under `target`.
- Add unit/integration tests (if available in this repo) covering entry names like `/tmp/evil`, `\
\server\share\evil` (Windows), and `C:\evil`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. check_path_traversal lacks tests 📘 Rule violation ☼ Reliability
Description
New validation rejects archive entries containing .. components in uncompress_pkg() and
uncompress_tar(), but this behavior change is not accompanied by targeted tests. This risks
regressions and gaps in coverage for a security-sensitive extraction path.
Code

rust/src/files.rs[228]

+            check_path_traversal(Path::new(name))?;
Evidence
Rule 5 requires adding or updating tests when behavior changes. The PR introduces
check_path_traversal() and wires it into both archive extraction flows, but no corresponding test
additions are present alongside these new checks.

AGENTS.md: Add or Update Tests for Changes; Prefer Small Unit Tests and Avoid Mocks
rust/src/files.rs[95-103]
rust/src/files.rs[219-236]
rust/src/files.rs[371-386]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The PR adds path traversal validation during archive extraction, but does not add tests to confirm malicious paths are rejected and safe paths still extract.

## Issue Context
The behavior change occurs in `uncompress_pkg()` and `uncompress_tar()` via `check_path_traversal()`. Because this is security-sensitive and error-path driven, tests should cover both allowed and rejected cases.

## Fix Focus Areas
- rust/src/files.rs[95-103]
- rust/src/files.rs[219-236]
- rust/src/files.rs[371-386]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

7. uncompress_* now errors on paths 📘 Rule violation ⚙ Maintainability
Description
uncompress_pkg() and uncompress_tar() now reject entries with .., absolute, or prefixed paths
by returning an error, which is a user-visible behavior change for callers that previously succeeded
on such archives. This can be considered a breaking compatibility change unless documented as an
intentional security-hardening change for consumers.
Code

rust/src/files.rs[R95-109]

+pub fn check_path_traversal(entry_path: &Path) -> Result<(), Error> {
+    if entry_path
+        .components()
+        .any(|c| {
+            matches!(
+                c,
+                std::path::Component::ParentDir
+                    | std::path::Component::RootDir
+                    | std::path::Component::Prefix(_)
+            )
+        })
+    {
+        return Err(anyhow!("Unsafe entry (path traversal): {:?}", entry_path));
+    }
+    Ok(())
Evidence
PR Compliance ID 1 requires avoiding breaking changes to public behavior. The added
check_path_traversal() returns an error for certain paths, and the PR wires it into
uncompress_pkg() and uncompress_tar(), changing behavior from previously extracting those
entries to now returning an error.

AGENTS.md: Maintain API/ABI Compatibility (No Breaking Changes to Public Interfaces)
rust/src/files.rs[95-109]
rust/src/files.rs[226-239]
rust/src/files.rs[378-393]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`uncompress_pkg()` / `uncompress_tar()` now fail fast for archive entries containing `ParentDir(..)`, `RootDir`, or `Prefix(_)`, which is a user-visible behavior change for some inputs and may be considered breaking without explicit documentation.

## Issue Context
This PR introduces security hardening for archive extraction by rejecting unsafe paths. To preserve upgrade expectations, the change should be explicitly documented for users (e.g., release notes / changelog entry describing that such archives will now error rather than extract).

## Fix Focus Areas
- rust/src/files.rs[95-109]
- rust/src/files.rs[226-239]
- rust/src/files.rs[378-393]
- rust/CHANGELOG.md[1-7]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


8. Traversal rejection not logged 📘 Rule violation ◔ Observability
Description
When a traversal path is detected, the code returns an error without emitting any user-relevant log
entry, which can make extraction failures harder to diagnose. Adding a warning/error log at the
rejection point (or at call sites) would improve operational insight.
Code

rust/src/files.rs[R95-101]

+pub fn check_path_traversal(entry_path: &Path) -> Result<(), Error> {
+    if entry_path
+        .components()
+        .any(|c| matches!(c, std::path::Component::ParentDir))
+    {
+        return Err(anyhow!("Unsafe entry (path traversal): {:?}", entry_path));
+    }
Evidence
Rule 8 calls for user-relevant logging where it improves insight. The new failure path returns
Err(anyhow!(...)) for traversal detection, but does not log the rejection in the new code path.

AGENTS.md: Add User-Relevant Logging Where It Improves Insight
rust/src/files.rs[95-101]
rust/src/files.rs[225-233]
rust/src/files.rs[379-385]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`check_path_traversal()` rejects unsafe entries by returning an error, but no log line is emitted when this occurs.

## Issue Context
This is a new failure path added to extraction flows; logging the rejected entry name/path would help users understand why extraction failed.

## Fix Focus Areas
- rust/src/files.rs[95-101]
- rust/src/files.rs[225-233]
- rust/src/files.rs[379-385]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Previous review results

Review updated until commit 9169379

Results up to commit eeda520


🐞 Bugs (1) 📘 Rule violations (2) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0)


Action required
1. check_path_traversal lacks tests 📘 Rule violation ☼ Reliability
Description
New validation rejects archive entries containing .. components in uncompress_pkg() and
uncompress_tar(), but this behavior change is not accompanied by targeted tests. This risks
regressions and gaps in coverage for a security-sensitive extraction path.
Code

rust/src/files.rs[228]

+            check_path_traversal(Path::new(name))?;
Evidence
Rule 5 requires adding or updating tests when behavior changes. The PR introduces
check_path_traversal() and wires it into both archive extraction flows, but no corresponding test
additions are present alongside these new checks.

AGENTS.md: Add or Update Tests for Changes; Prefer Small Unit Tests and Avoid Mocks
rust/src/files.rs[95-103]
rust/src/files.rs[219-236]
rust/src/files.rs[371-386]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The PR adds path traversal validation during archive extraction, but does not add tests to confirm malicious paths are rejected and safe paths still extract.

## Issue Context
The behavior change occurs in `uncompress_pkg()` and `uncompress_tar()` via `check_path_traversal()`. Because this is security-sensitive and error-path driven, tests should cover both allowed and rejected cases.

## Fix Focus Areas
- rust/src/files.rs[95-103]
- rust/src/files.rs[219-236]
- rust/src/files.rs[371-386]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Absolute path escape 🐞 Bug ⛨ Security
Description
check_path_traversal() only rejects ParentDir (..) components, so absolute/prefixed entry paths
pass validation. In uncompress_pkg(), an absolute name can cause target_path.join(name) to
ignore target_path and write outside the extraction directory.
Code

rust/src/files.rs[R225-231]

        while let Some(next) = cpio_reader.next() {
            let entry = next?;
            let name = entry.name();
+            check_path_traversal(Path::new(name))?;
            let mut file = Vec::new();
            cpio_reader.read_to_end(&mut file)?;
            let target_path_buf = target_path.join(name);
Evidence
The validator only checks for Component::ParentDir, so it does not reject absolute/prefixed paths.
uncompress_pkg() then uses the raw archive name in target_path.join(name) and writes to that
resulting path, enabling writes outside the intended target when name is absolute/prefixed.

rust/src/files.rs[95-103]
rust/src/files.rs[219-237]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`check_path_traversal()` currently only rejects `..` path components. Absolute paths (Unix `/etc/passwd`) and Windows-style prefixed paths (e.g., `C:\Windows\...`, UNC) can still pass validation and escape the intended extraction root when joined with `target`.

## Issue Context
`uncompress_pkg()` validates `entry.name()` with `check_path_traversal(Path::new(name))` and then writes to `target_path.join(name)`. If `name` is absolute/prefixed, the joined path may resolve outside `target`.

## Fix Focus Areas
- rust/src/files.rs[95-103]
- rust/src/files.rs[219-237]

### Suggested fix
- Update `check_path_traversal()` to reject any non-relative components, not just `ParentDir`, e.g. fail on `Component::RootDir` and `Component::Prefix(_)` as well.
- Optionally add a defensive post-join check in `uncompress_pkg()` (and any similar extraction code): after building the output path, ensure it is not absolute and is lexically under `target`.
- Add unit/integration tests (if available in this repo) covering entry names like `/tmp/evil`, `\
\server\share\evil` (Windows), and `C:\evil`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended
3. Traversal rejection not logged 📘 Rule violation ◔ Observability
Description
When a traversal path is detected, the code returns an error without emitting any user-relevant log
entry, which can make extraction failures harder to diagnose. Adding a warning/error log at the
rejection point (or at call sites) would improve operational insight.
Code

rust/src/files.rs[R95-101]

+pub fn check_path_traversal(entry_path: &Path) -> Result<(), Error> {
+    if entry_path
+        .components()
+        .any(|c| matches!(c, std::path::Component::ParentDir))
+    {
+        return Err(anyhow!("Unsafe entry (path traversal): {:?}", entry_path));
+    }
Evidence
Rule 8 calls for user-relevant logging where it improves insight. The new failure path returns
Err(anyhow!(...)) for traversal detection, but does not log the rejection in the new code path.

AGENTS.md: Add User-Relevant Logging Where It Improves Insight
rust/src/files.rs[95-101]
rust/src/files.rs[225-233]
rust/src/files.rs[379-385]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`check_path_traversal()` rejects unsafe entries by returning an error, but no log line is emitted when this occurs.

## Issue Context
This is a new failure path added to extraction flows; logging the rejected entry name/path would help users understand why extraction failed.

## Fix Focus Areas
- rust/src/files.rs[95-101]
- rust/src/files.rs[225-233]
- rust/src/files.rs[379-385]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Results up to commit 2f8fd28


🐞 Bugs (1) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0)


Action required
1. Tar symlink escape 🐞 Bug ⛨ Security
Description
uncompress_tar() only rejects .. components, then unconditionally calls
entry_decoder.unpack(entry_target), which can create symlinks/hardlinks from the archive. A
malicious tar can first create a symlink inside the target (e.g., link -> /etc) and then write
link/passwd, escaping the extraction directory despite passing the .. check.
Code

rust/src/files.rs[R379-385]

    for entry in archive.entries()? {
        let mut entry_decoder = entry?;
        let entry_path: PathBuf = entry_decoder.path()?.iter().skip(1).collect();
+        check_path_traversal(&entry_path)?;
        let entry_target = target.join(entry_path);
        fs::create_dir_all(entry_target.parent().unwrap())?;
        entry_decoder.unpack(entry_target)?;
Evidence
The repo’s new validator only rejects .. path components, and uncompress_tar() still unpacks
entries directly to the filesystem without checking for link entry types. This enables link-based
escapes that do not require .. components in the entry path.

rust/src/files.rs[95-103]
rust/src/files.rs[371-386]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`uncompress_tar()` currently validates paths only by rejecting `..` components, but then unpacks every tar entry as-is. Tar archives can contain symlinks and hardlinks; extracting them allows later entries to write outside the intended extraction directory by writing through those links.

## Issue Context
- `check_path_traversal()` only checks for `Component::ParentDir` and does not account for link-based escapes.
- `uncompress_tar()` uses `entry_decoder.unpack(entry_target)` without checking the tar entry type or preventing symlink/hardlink creation.

## Fix Focus Areas
- rust/src/files.rs[95-103]
- rust/src/files.rs[371-386]

## What to change
1. In `uncompress_tar()`, inspect each tar entry’s type (via the tar header) before unpacking.
2. Reject (return an error) for symlink and hardlink entry types (and any other non-regular types you don’t explicitly support).
  - If directory entries are expected, allow directories.
  - If only regular files are expected for these tarballs, allow only regular files.
3. (Optional but stronger) Add a defense-in-depth check that the extraction path does not traverse through symlinks already present on disk (walk parent components, using `symlink_metadata`, and fail if any component is a symlink).

## Suggested tests
Add a unit test that builds a tar containing:
- an entry that creates a symlink inside the extraction directory
- a subsequent entry that writes through that symlink
and assert extraction fails (or the escaped path is not written).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Results up to commit 020978d


🐞 Bugs (1) 📘 Rule violations (1) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0)


Action required
1. Tar.gz bypasses validation 🐞 Bug ⛨ Security
Description
check_path_traversal() is never applied to the .gz extraction path: uncompress() dispatches
GZ to untargz(), which calls Archive::unpack() directly without validating archive entry
paths. As a result, tar.gz remains outside the PR’s “reject unsafe entries” behavior, undermining
the stated traversal prevention for tar extraction.
Code

rust/src/files.rs[R95-110]

+pub fn check_path_traversal(entry_path: &Path) -> Result<(), Error> {
+    if entry_path
+        .components()
+        .any(|c| {
+            matches!(
+                c,
+                std::path::Component::ParentDir
+                    | std::path::Component::RootDir
+                    | std::path::Component::Prefix(_)
+            )
+        })
+    {
+        return Err(anyhow!("Unsafe entry (path traversal): {:?}", entry_path));
+    }
+    Ok(())
+}
Evidence
The repo’s main decompression dispatcher sends GZ files to untargz(), but untargz() does not
call the newly added check_path_traversal() and instead performs a direct archive unpack;
therefore tar.gz extraction is not covered by the PR’s new validation behavior.

rust/src/files.rs[95-110]
rust/src/files.rs[149-167]
rust/src/files.rs[360-375]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The PR introduces `check_path_traversal()` and uses it in `uncompress_pkg()` and `uncompress_tar()`, but `.tar.gz` files are extracted via `untargz()` which does not validate entry paths.

### Issue Context
`uncompress()` routes `GZ` to `untargz()`, and `untargz()` uses `tar::Archive::unpack()` without calling `check_path_traversal()` on each entry. This means the security behavior added in this PR is not applied to tar.gz.

### Fix Focus Areas
- rust/src/files.rs[149-167]
- rust/src/files.rs[360-375]

### Suggested fix approach
- Refactor `untargz()` to iterate `archive.entries()?` and, for each entry:
 - read `entry.path()?` (or equivalent),
 - apply `check_path_traversal()` to that path,
 - unpack the entry into the intended destination (e.g., by joining to `parent_path` after validation, or using an unpack-into-directory API if available).
- Optionally add a unit test similar to `uncompress_tar_rejects_path_traversal_entry`, but covering the `.gz` path to prevent regressions.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended
2. uncompress_* now errors on paths 📘 Rule violation ⚙ Maintainability
Description
uncompress_pkg() and uncompress_tar() now reject entries with .., absolute, or prefixed paths
by returning an error, which is a user-visible behavior change for callers that previously succeeded
on such archives. This can be considered a breaking compatibility change unless documented as an
intentional security-hardening change for consumers.
Code

rust/src/files.rs[R95-109]

+pub fn check_path_traversal(entry_path: &Path) -> Result<(), Error> {
+    if entry_path
+        .components()
+        .any(|c| {
+            matches!(
+                c,
+                std::path::Component::ParentDir
+                    | std::path::Component::RootDir
+                    | std::path::Component::Prefix(_)
+            )
+        })
+    {
+        return Err(anyhow!("Unsafe entry (path traversal): {:?}", entry_path));
+    }
+    Ok(())
Evidence
PR Compliance ID 1 requires avoiding breaking changes to public behavior. The added
check_path_traversal() returns an error for certain paths, and the PR wires it into
uncompress_pkg() and uncompress_tar(), changing behavior from previously extracting those
entries to now returning an error.

AGENTS.md: Maintain API/ABI Compatibility (No Breaking Changes to Public Interfaces)
rust/src/files.rs[95-109]
rust/src/files.rs[226-239]
rust/src/files.rs[378-393]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`uncompress_pkg()` / `uncompress_tar()` now fail fast for archive entries containing `ParentDir(..)`, `RootDir`, or `Prefix(_)`, which is a user-visible behavior change for some inputs and may be considered breaking without explicit documentation.

## Issue Context
This PR introduces security hardening for archive extraction by rejecting unsafe paths. To preserve upgrade expectations, the change should be explicitly documented for users (e.g., release notes / changelog entry describing that such archives will now error rather than extract).

## Fix Focus Areas
- rust/src/files.rs[95-109]
- rust/src/files.rs[226-239]
- rust/src/files.rs[378-393]
- rust/CHANGELOG.md[1-7]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Results up to commit 58424fb


🐞 Bugs (1) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0)


Action required
1. Tar first segment always dropped 🐞 Bug ≡ Correctness
Description
uncompress_tar() always does iter().skip(1) on every entry path, so single-component entries (e.g.,
"file.txt") become an empty path and are unpacked to target itself. This can overwrite the
intended extraction directory path with a file or cause extraction failures for tarballs that don't
include a top-level folder.
Code

rust/src/files.rs[R385-389]

        let entry_path: PathBuf = entry_decoder.path()?.iter().skip(1).collect();
+        check_path_traversal(&entry_path)?;
        let entry_target = target.join(entry_path);
        fs::create_dir_all(entry_target.parent().unwrap())?;
        entry_decoder.unpack(entry_target)?;
Evidence
The tar extraction path always drops the first component, then joins the (possibly empty) path onto
target and unpacks. In contrast, the zip extraction path only drops the first component when the
path has more than one component, which avoids producing an empty relative path for flat archives.

rust/src/files.rs[375-390]
rust/src/files.rs[419-432]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`uncompress_tar()` unconditionally strips the first path component (`iter().skip(1)`), which can turn a valid tar entry path with a single component into an empty path. That causes `entry_target` to resolve to the extraction root (`target`) and `unpack()` may write a file at the `target` path or fail when the code expects `target` to be a directory.

### Issue Context
`unzip()` already has logic to strip the first component only when the archive paths actually contain a parent folder; tar extraction should behave similarly.

### Fix Focus Areas
- rust/src/files.rs[375-390]
- rust/src/files.rs[419-432]

### Suggested fix
- Mirror the `unzip()` approach:
 - Count components (or otherwise detect whether there is a top-level folder).
 - Only `skip(1)` when there is more than one component.
 - Otherwise, keep the original path.
- Additionally, consider explicitly rejecting an empty `entry_path` for regular-file entries to avoid writing directly to `target`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Results up to commit 35a1ad3


🐞 Bugs (1) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0)


Action required
1. PKG empty name accepted 🐞 Bug ≡ Correctness
Description
uncompress_pkg() validates ../absolute/prefixed paths but does not reject an empty
entry.name(), so target.join("") resolves to the extraction root and fs::write() may
create/overwrite the target path as a file instead of a directory. This can cause extraction
failures or clobber the intended extraction directory when the target path does not yet exist.
Code

rust/src/files.rs[R231-235]

            let name = entry.name();
+            check_path_traversal(Path::new(name))?;
            let mut file = Vec::new();
            cpio_reader.read_to_end(&mut file)?;
            let target_path_buf = target_path.join(name);
Evidence
In uncompress_pkg(), the entry name is validated only via check_path_traversal(Path::new(name)),
but check_path_traversal() only rejects ParentDir/RootDir/Prefix components; an empty path has no
components and passes. The code then builds target_path_buf = target_path.join(name) and writes to
it, so an empty name targets the extraction root itself. By contrast, uncompress_tar() explicitly
rejects empty paths, showing this is an expected safety check in extraction code.

rust/src/files.rs[95-107]
rust/src/files.rs[223-253]
rust/src/files.rs[375-399]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`uncompress_pkg()` calls `check_path_traversal(Path::new(name))`, but `check_path_traversal()` does not reject empty paths. If a CPIO entry name is `""`, then `target_path.join(name)` resolves to `target` itself, and `fs::write(&target_path_buf, file)` may create/overwrite the extraction root path as a file (especially when `target` doesn’t exist yet).

## Issue Context
The tar extraction path already explicitly rejects an empty entry path; pkg/cpio should match that safety behavior.

## Fix Focus Areas
- rust/src/files.rs[223-253]
- rust/src/files.rs[95-107]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Qodo Logo

@selenium-ci selenium-ci added C-rust Rust code is mostly Selenium Manager B-manager Selenium Manager labels Jun 11, 2026
@qodo-code-review

Copy link
Copy Markdown
Contributor

PR Summary by Qodo

Prevent path traversal in tar and pkg extraction
🐞 Bug fix 🕐 10-20 Minutes

Grey Divider

Walkthroughs

Description
• Reject archive entries containing ".." path components during tar/cpio extraction.
• Centralize traversal validation in a shared check_path_traversal() helper.
• Fail fast with a clear error before writing any unsafe paths to disk.
Diagram
graph TD
  A["uncompress_tar()"] --> B["check_path_traversal()"] --> D[("Filesystem write")]
  C["uncompress_pkg()"] --> B --> D
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Validate by containment (canonicalize joined path)
  • ➕ Catches more cases than just .. (e.g., absolute paths, Windows prefixes)
  • ➕ Guarantees the final resolved output stays within target
  • ➖ Requires filesystem access (canonicalize) which can be tricky for non-existent intermediate paths
  • ➖ Must carefully handle symlinks to avoid time-of-check/time-of-use pitfalls
2. Use library-provided “safe unpack” APIs where available
  • ➕ Some archive crates provide extraction helpers designed to prevent path traversal (e.g., tar entry unpack-in-directory patterns)
  • ➕ Reduces risk of missing edge cases in custom validation
  • ➖ May require API changes/refactor of current extraction logic
  • ➖ Not always available for all archive formats (e.g., cpio payloads)
3. Harden checks beyond ParentDir
  • ➕ Low-cost improvement: also reject absolute paths and Windows Prefix components, and normalize .
  • ➕ Keeps current extraction approach while improving coverage
  • ➖ Still a custom security filter that must track platform/path semantics correctly

Recommendation: The current approach (explicitly rejecting ParentDir(..) components) is a good immediate mitigation and keeps changes small. As a follow-up hardening step, consider also rejecting absolute paths / Windows prefix components and/or switching tar extraction to a crate API that enforces “unpack within directory” semantics, to cover more traversal variants than .. alone.

Grey Divider

File Changes

Bug fix (1)
files.rs Add shared path-traversal guard to tar and pkg extraction +12/-0

Add shared path-traversal guard to tar and pkg extraction

• Introduces 'check_path_traversal()' to reject paths containing '..' components. Calls this validation for each PKG (cpio) entry name and each TAR entry path before creating directories and unpacking/writing files.

rust/src/files.rs


Grey Divider

Qodo Logo

Comment thread rust/src/files.rs
while let Some(next) = cpio_reader.next() {
let entry = next?;
let name = entry.name();
check_path_traversal(Path::new(name))?;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. check_path_traversal lacks tests 📘 Rule violation ☼ Reliability

New validation rejects archive entries containing .. components in uncompress_pkg() and
uncompress_tar(), but this behavior change is not accompanied by targeted tests. This risks
regressions and gaps in coverage for a security-sensitive extraction path.
Agent Prompt
## Issue description
The PR adds path traversal validation during archive extraction, but does not add tests to confirm malicious paths are rejected and safe paths still extract.

## Issue Context
The behavior change occurs in `uncompress_pkg()` and `uncompress_tar()` via `check_path_traversal()`. Because this is security-sensitive and error-path driven, tests should cover both allowed and rejected cases.

## Fix Focus Areas
- rust/src/files.rs[95-103]
- rust/src/files.rs[219-236]
- rust/src/files.rs[371-386]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread rust/src/files.rs
Comment on lines 225 to 231
while let Some(next) = cpio_reader.next() {
let entry = next?;
let name = entry.name();
check_path_traversal(Path::new(name))?;
let mut file = Vec::new();
cpio_reader.read_to_end(&mut file)?;
let target_path_buf = target_path.join(name);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

3. Absolute path escape 🐞 Bug ⛨ Security

check_path_traversal() only rejects ParentDir (..) components, so absolute/prefixed entry paths
pass validation. In uncompress_pkg(), an absolute name can cause target_path.join(name) to
ignore target_path and write outside the extraction directory.
Agent Prompt
## Issue description
`check_path_traversal()` currently only rejects `..` path components. Absolute paths (Unix `/etc/passwd`) and Windows-style prefixed paths (e.g., `C:\Windows\...`, UNC) can still pass validation and escape the intended extraction root when joined with `target`.

## Issue Context
`uncompress_pkg()` validates `entry.name()` with `check_path_traversal(Path::new(name))` and then writes to `target_path.join(name)`. If `name` is absolute/prefixed, the joined path may resolve outside `target`.

## Fix Focus Areas
- rust/src/files.rs[95-103]
- rust/src/files.rs[219-237]

### Suggested fix
- Update `check_path_traversal()` to reject any non-relative components, not just `ParentDir`, e.g. fail on `Component::RootDir` and `Component::Prefix(_)` as well.
- Optionally add a defensive post-join check in `uncompress_pkg()` (and any similar extraction code): after building the output path, ensure it is not absolute and is lexically under `target`.
- Add unit/integration tests (if available in this repo) covering entry names like `/tmp/evil`, `\\server\share\evil` (Windows), and `C:\evil`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@bonigarcia bonigarcia force-pushed the sm_security_path_traversal_fix branch from eeda520 to 2f8fd28 Compare June 11, 2026 09:27
@qodo-code-review

qodo-code-review Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit 2f8fd28

Comment thread rust/src/files.rs
Comment on lines 379 to 385
for entry in archive.entries()? {
let mut entry_decoder = entry?;
let entry_path: PathBuf = entry_decoder.path()?.iter().skip(1).collect();
check_path_traversal(&entry_path)?;
let entry_target = target.join(entry_path);
fs::create_dir_all(entry_target.parent().unwrap())?;
entry_decoder.unpack(entry_target)?;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Tar symlink escape 🐞 Bug ⛨ Security

uncompress_tar() only rejects .. components, then unconditionally calls
entry_decoder.unpack(entry_target), which can create symlinks/hardlinks from the archive. A
malicious tar can first create a symlink inside the target (e.g., link -> /etc) and then write
link/passwd, escaping the extraction directory despite passing the .. check.
Agent Prompt
## Issue description
`uncompress_tar()` currently validates paths only by rejecting `..` components, but then unpacks every tar entry as-is. Tar archives can contain symlinks and hardlinks; extracting them allows later entries to write outside the intended extraction directory by writing through those links.

## Issue Context
- `check_path_traversal()` only checks for `Component::ParentDir` and does not account for link-based escapes.
- `uncompress_tar()` uses `entry_decoder.unpack(entry_target)` without checking the tar entry type or preventing symlink/hardlink creation.

## Fix Focus Areas
- rust/src/files.rs[95-103]
- rust/src/files.rs[371-386]

## What to change
1. In `uncompress_tar()`, inspect each tar entry’s type (via the tar header) before unpacking.
2. Reject (return an error) for symlink and hardlink entry types (and any other non-regular types you don’t explicitly support).
   - If directory entries are expected, allow directories.
   - If only regular files are expected for these tarballs, allow only regular files.
3. (Optional but stronger) Add a defense-in-depth check that the extraction path does not traverse through symlinks already present on disk (walk parent components, using `symlink_metadata`, and fail if any component is a symlink).

## Suggested tests
Add a unit test that builds a tar containing:
- an entry that creates a symlink inside the extraction directory
- a subsequent entry that writes through that symlink
and assert extraction fails (or the escaped path is not written).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@bonigarcia bonigarcia force-pushed the sm_security_path_traversal_fix branch from 2f8fd28 to 020978d Compare June 11, 2026 09:32
@qodo-code-review

qodo-code-review Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit 020978d

Comment thread rust/src/files.rs
Comment on lines +95 to +110
pub fn check_path_traversal(entry_path: &Path) -> Result<(), Error> {
if entry_path
.components()
.any(|c| {
matches!(
c,
std::path::Component::ParentDir
| std::path::Component::RootDir
| std::path::Component::Prefix(_)
)
})
{
return Err(anyhow!("Unsafe entry (path traversal): {:?}", entry_path));
}
Ok(())
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. Tar.gz bypasses validation 🐞 Bug ⛨ Security

check_path_traversal() is never applied to the .gz extraction path: uncompress() dispatches
GZ to untargz(), which calls Archive::unpack() directly without validating archive entry
paths. As a result, tar.gz remains outside the PR’s “reject unsafe entries” behavior, undermining
the stated traversal prevention for tar extraction.
Agent Prompt
### Issue description
The PR introduces `check_path_traversal()` and uses it in `uncompress_pkg()` and `uncompress_tar()`, but `.tar.gz` files are extracted via `untargz()` which does not validate entry paths.

### Issue Context
`uncompress()` routes `GZ` to `untargz()`, and `untargz()` uses `tar::Archive::unpack()` without calling `check_path_traversal()` on each entry. This means the security behavior added in this PR is not applied to tar.gz.

### Fix Focus Areas
- rust/src/files.rs[149-167]
- rust/src/files.rs[360-375]

### Suggested fix approach
- Refactor `untargz()` to iterate `archive.entries()?` and, for each entry:
  - read `entry.path()?` (or equivalent),
  - apply `check_path_traversal()` to that path,
  - unpack the entry into the intended destination (e.g., by joining to `parent_path` after validation, or using an unpack-into-directory API if available).
- Optionally add a unit test similar to `uncompress_tar_rejects_path_traversal_entry`, but covering the `.gz` path to prevent regressions.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@bonigarcia bonigarcia force-pushed the sm_security_path_traversal_fix branch from 020978d to 58424fb Compare June 11, 2026 09:38
@qodo-code-review

qodo-code-review Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit 58424fb

Comment thread rust/src/files.rs Outdated
Comment on lines 385 to 389
let entry_path: PathBuf = entry_decoder.path()?.iter().skip(1).collect();
check_path_traversal(&entry_path)?;
let entry_target = target.join(entry_path);
fs::create_dir_all(entry_target.parent().unwrap())?;
entry_decoder.unpack(entry_target)?;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Tar first segment always dropped 🐞 Bug ≡ Correctness

uncompress_tar() always does iter().skip(1) on every entry path, so single-component entries (e.g.,
"file.txt") become an empty path and are unpacked to target itself. This can overwrite the
intended extraction directory path with a file or cause extraction failures for tarballs that don't
include a top-level folder.
Agent Prompt
### Issue description
`uncompress_tar()` unconditionally strips the first path component (`iter().skip(1)`), which can turn a valid tar entry path with a single component into an empty path. That causes `entry_target` to resolve to the extraction root (`target`) and `unpack()` may write a file at the `target` path or fail when the code expects `target` to be a directory.

### Issue Context
`unzip()` already has logic to strip the first component only when the archive paths actually contain a parent folder; tar extraction should behave similarly.

### Fix Focus Areas
- rust/src/files.rs[375-390]
- rust/src/files.rs[419-432]

### Suggested fix
- Mirror the `unzip()` approach:
  - Count components (or otherwise detect whether there is a top-level folder).
  - Only `skip(1)` when there is more than one component.
  - Otherwise, keep the original path.
- Additionally, consider explicitly rejecting an empty `entry_path` for regular-file entries to avoid writing directly to `target`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@bonigarcia bonigarcia force-pushed the sm_security_path_traversal_fix branch from 58424fb to 35a1ad3 Compare June 11, 2026 09:52
@qodo-code-review

qodo-code-review Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit 35a1ad3

Comment thread rust/src/files.rs
Comment on lines 231 to 235
let name = entry.name();
check_path_traversal(Path::new(name))?;
let mut file = Vec::new();
cpio_reader.read_to_end(&mut file)?;
let target_path_buf = target_path.join(name);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Pkg empty name accepted 🐞 Bug ≡ Correctness

uncompress_pkg() validates ../absolute/prefixed paths but does not reject an empty
entry.name(), so target.join("") resolves to the extraction root and fs::write() may
create/overwrite the target path as a file instead of a directory. This can cause extraction
failures or clobber the intended extraction directory when the target path does not yet exist.
Agent Prompt
## Issue description
`uncompress_pkg()` calls `check_path_traversal(Path::new(name))`, but `check_path_traversal()` does not reject empty paths. If a CPIO entry name is `""`, then `target_path.join(name)` resolves to `target` itself, and `fs::write(&target_path_buf, file)` may create/overwrite the extraction root path as a file (especially when `target` doesn’t exist yet).

## Issue Context
The tar extraction path already explicitly rejects an empty entry path; pkg/cpio should match that safety behavior.

## Fix Focus Areas
- rust/src/files.rs[223-253]
- rust/src/files.rs[95-107]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Add validation to reject archive entries containing ParentDir (..) components
in uncompress_tar() and uncompress_pkg(). This prevents malicious archives
from writing files outside the intended extraction directory.

The shared validation logic is refactored into check_path_traversal()
to avoid duplication (DRY principle).

- CVE-2025-XXXX: Path Traversal via uncompress_tar
- CVE-2025-YYYY: Path Traversal via uncompress_pkg
@bonigarcia bonigarcia force-pushed the sm_security_path_traversal_fix branch from 35a1ad3 to 9169379 Compare June 11, 2026 09:58
@qodo-code-review

qodo-code-review Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit 9169379

@qodo-code-review

Copy link
Copy Markdown
Contributor

CI Feedback 🧐

A test triggered by this PR failed. Here is an AI-generated analysis of the failure:

Action: CI Success

Failed stage: Verify required jobs succeeded [❌]

Failed test name: ""

Failure summary:

The workflow job CI Success failed intentionally because it detected that at least one required job
in the workflow failed.
- A step ran a shell script that prints One or more required jobs failed and
then executes exit 1, causing the job to fail with exit code 1.
- The log excerpt does not include
which required job(s) failed; it only shows the final aggregator/guard step failing.

Relevant error logs:
1:  ##[group]Runner Image Provisioner
2:  Hosted Compute Agent
...

14:  Image: ubuntu-24.04
15:  Version: 20260525.161.1
16:  Included Software: https://github.com/actions/runner-images/blob/ubuntu24/20260525.161/images/ubuntu/Ubuntu2404-Readme.md
17:  Image Release: https://github.com/actions/runner-images/releases/tag/ubuntu24%2F20260525.161
18:  ##[endgroup]
19:  ##[group]GITHUB_TOKEN Permissions
20:  Contents: read
21:  Metadata: read
22:  ##[endgroup]
23:  Secret source: Actions
24:  Prepare workflow directory
25:  Prepare all required actions
26:  Complete job name: CI Success
27:  ##[group]Run if true; then
28:  �[36;1mif true; then�[0m
29:  �[36;1m  echo "One or more required jobs failed"�[0m
30:  �[36;1m  exit 1�[0m
31:  �[36;1mfi�[0m
32:  shell: /usr/bin/bash -e {0}
33:  ##[endgroup]
34:  One or more required jobs failed
35:  ##[error]Process completed with exit code 1.
36:  Cleaning up orphan processes

Comment thread rust/src/files.rs
} else {
path.to_path_buf()
};
if entry_path.as_os_str().is_empty() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this since 2 lines later we do it again in check_path_traversal?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

B-manager Selenium Manager C-rust Rust code is mostly Selenium Manager

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants