CVE Patch Review

CVE-2026-46383: Root-cause Tar Extraction Path Validation for Windows TarSlip

CVE-2026-46383 · GHSA-MQ5J-PW29-JCV3 · Updated 2026-05-15 Root-cause

Summary

The patch addresses a Windows-specific TarSlip/arbitrary file overwrite issue in Microsoft APM by validating tar member names before extraction in both the legacy bundle probe and the unpacker. It adds explicit rejection of absolute Unix paths, Windows drive-qualified paths, Windows absolute paths, and traversal segments via shared path validation, plus regression tests for these cases. Based on the provided diff, the fix appears to correct the underlying trust boundary failure rather than only blocking a single payload shape.

Analysis

Vulnerability

CVE-2026-46383 is an arbitrary file overwrite issue in Microsoft APM before 0.13.0 on Windows during tar archive extraction. The vulnerable behavior is consistent with TarSlip: archive member names were trusted and passed into extraction logic without sufficient normalization and boundary enforcement, allowing crafted entries to escape the intended destination and overwrite attacker-chosen files when a user installs a malicious tarball. The advisory and CVE context are documented in the GHSA advisory, NVD record, and CVE record.

The patch diff shows two relevant vulnerable patterns. In src/apm_cli/bundle/local_bundle.py, the code performed a direct tar.extractall(tmp) during legacy bundle probing. In src/apm_cli/bundle/unpacker.py, the prior checks were too narrow, relying on conditions like member.name.startswith("/") or ".." in member.name. That approach is insufficient on Windows because drive-qualified and other absolute Windows path forms can bypass Unix-centric checks.

tar.extractall(tmp)  # noqa: S202

if member.name.startswith("/") or ".." in member.name:
    raise ValueError(f"Refusing to extract path-traversal entry: {member.name}")

The root cause is incomplete validation of archive member paths across platform-specific path syntaxes before extraction. In particular, Windows absolute paths such as D:/evil/payload.txt and UNC-like forms such as //server/share/payload.txt were not comprehensively rejected by the earlier logic, enabling writes outside the extraction root.

Patch

The patch in commit 77d1dda8303c8d7ccb6148788a6274fdece98499 strengthens validation in both extraction-related paths.

First, the legacy bundle probe in local_bundle.py now validates each tar member name before calling extractall. It rejects:

  • Unix absolute paths via name.startswith("/")
  • Windows drive-qualified paths via PureWindowsPath(name).drive
  • Windows absolute paths via PureWindowsPath(name).is_absolute()
  • Traversal segments via shared validate_path_segments(...) raising PathTraversalError
name = member.name
if (
    name.startswith("/")
    or PureWindowsPath(name).drive
    or PureWindowsPath(name).is_absolute()
):
    return False
try:
    validate_path_segments(name, context="tar member")
except PathTraversalError:
    return False
tar.extractall(tmp)  # noqa: S202 -- validated above

Second, the unpacker now imports PureWindowsPath and the shared path-security helpers, replacing the simplistic string check with the same broader validation model. This is important because it aligns both the preflight/probe path and the actual unpack path around the same security assumptions.

from pathlib import Path, PureWindowsPath
from ..utils.path_security import PathTraversalError, validate_path_segments

name = member.name
if (
    name.startswith("/")
    or PureWindowsPath(name).drive
    or PureWindowsPath(name).is_absolute()
):
    raise ValueError(f"Refusing to extract path-traversal entry: {name}")
try:
    validate_path_segments(name, context="tar member")
except PathTraversalError:
    raise ValueError(
        f"Refusing to extract path-traversal entry: {name}"
    ) from None

The test file tests/unit/bundle/test_tar_windows_absolute_path.py adds regression coverage for Windows drive-letter paths, UNC-style paths, Unix absolute paths, dot-dot traversal, valid bundles, and a negative assertion that no file is created outside the temporary extraction area. This materially improves confidence that the issue is fixed in both code paths.

Review

Pros

  • The patch addresses the actual trust boundary: tar member names are validated before extraction rather than relying on post hoc assumptions.
  • It closes the Windows-specific gap by using PureWindowsPath to detect drive-qualified and absolute Windows paths, which the previous Unix-oriented checks missed.
  • It centralizes traversal handling through validate_path_segments and PathTraversalError, reducing the chance of divergent logic between components.
  • Both the legacy bundle probe and the unpacker are updated, which is important because the vulnerable extraction behavior existed in more than one path.
  • The regression tests are directly aligned with the reported issue and include both exploit-shaped inputs and a safety property check that no outside file is created.

Cons

  • The provided diff still uses tar.extractall(tmp) after validation in local_bundle.py. While acceptable if validation is complete, this keeps security dependent on the correctness and future maintenance of the pre-validation loop.
  • The snippets do not show a final canonicalization-and-prefix check against the destination root after joining extraction paths. Such a check is often a stronger invariant than member-name validation alone.
  • The review material does not show whether all tar entry types are constrained consistently in every path. One snippet references symlink/hardlink rejection, but the full surrounding logic is not visible here, so complete coverage cannot be confirmed from the excerpt alone.
  • The tests focus on path forms relevant to this CVE, but the provided material does not demonstrate coverage for mixed separators, unusual Windows namespace prefixes, or encoded edge cases.

Verdict

Root-cause.

Based on the supplied commit and tests, the patch appears to fix the underlying flaw: insufficient cross-platform validation of tar member paths before extraction. The change is not merely blocking one payload string; it broadens validation to cover Unix absolute paths, Windows drive paths, Windows absolute paths, and traversal segments, and it applies that logic in both the legacy probe and unpacker. That is consistent with a root-cause remediation for the reported Windows TarSlip overwrite described by the GHSA advisory and NVD entry.

The main residual concern is architectural rather than immediate: continued use of extractall means future regressions are possible if validation logic drifts. A defense-in-depth improvement would be to compute each destination path explicitly, canonicalize it, verify it remains under the extraction root, and then extract/write entries individually. Still, from the evidence in the patch commit, this fix is technically sound and appropriately targeted to the vulnerability.

Sources