Jul 30, 2026·5 min read·97 visits
An asymmetric path validation flaw in proot-distro prior to version 5.1.5 allows arbitrary host filesystem writes when extracting a malicious container image or backup archive containing crafted symbolic links.
CVE-2026-54574 (GHSA-9xq3-3fqg-4vg7) is a critical Symlink Escape and Arbitrary Host File Write vulnerability in proot-distro, an open-source utility for managing rootless PRoot containers on Termux and general Linux environments. The vulnerability is rooted in an asymmetric validation flaw during the archive extraction process of container installations, Docker/OCI layers, and container backup restorations. While the extraction engine successfully validated file names to prevent standard directory traversal (e.g., rejecting components containing '..'), it failed to validate symbolic link targets. An attacker could craft a malicious tar archive or container image that plants an absolute host-path symlink. Subsequent file members within the same archive could then traverse through this symlink, writing arbitrary files directly onto the host filesystem under the privileges of the executing process.
The utility proot-distro manages rootless PRoot containers on Termux and other Linux installations. During the extraction of tar archives—such as when installing containers, parsing Docker/OCI layers, or restoring backup archives—the application unpacks files into a dedicated target root directory (the container's rootfs). To prevent directory traversal, proot-distro sanitizes incoming member filenames, stripping leading slashes and discarding paths with traversal sequences like ...
However, a critical asymmetric validation flaw exists in versions prior to 5.1.5. Although the destination filenames are verified, the targets of symbolic links (member.linkname) are not validated. This permits an archive to plant a symlink pointing to an absolute or relative directory on the host filesystem.
When subsequent files inside the archive are extracted beneath the name of the symlink, the application resolves the path through the symlink. This results in file creation or modification directly on the host system outside the boundaries of the container's rootfs.
The root cause of this vulnerability lies in how Python's standard tarfile module interacts with symbolic links during sequential extraction when there is no runtime containment. In affected versions, the application processes directory traversal checks purely lexically on the member name, which fails to account for stateful changes on the filesystem during the extraction process.
If an archive contains a symlink member named evil targeting a host directory such as /data/data/com.termux/files/home, the extraction routine creates this symlink at <rootfs_dir>/evil. If a subsequent archive member is named evil/.bashrc, the destination path is generated using os.path.join(rootfs_dir, 'evil/.bashrc').
To write this regular file, the application invokes os.makedirs(os.path.dirname(dest), exist_ok=True) to create any parent directories. Because evil is already a symlink pointing to the host directory, the host operating system's filesystem APIs resolve the link. Consequently, open(dest, 'wb') is executed against /data/data/com.termux/files/home/.bashrc, writing the malicious content directly to the host filesystem.
The fix introduced in version 5.1.5 refactors the extraction logic in proot_distro/helpers/tar_extract.py by introducing a component-by-component path resolver named _safe_resolve(). This routine checks and clamps symlinks as they are evaluated.
def _safe_resolve(root, parts):
resolved: list = []
pending = list(parts)
link_budget = 40
while pending:
comp = pending.pop(0)
if comp in ("", "."):
continue
if comp == "..":
if resolved:
resolved.pop()
continue
current = os.path.join(root, *resolved, comp)
try:
st = os.lstat(current)
except OSError:
# Path does not exist yet; safe to append verbatim
resolved.append(comp)
continue
if stat.S_ISLNK(st.st_mode):
link_budget -= 1
if link_budget < 0:
return None
try:
target = os.readlink(current)
except OSError:
return None
tparts = target.split("/")
if target.startswith("/"):
resolved = [] # Re-root at container rootfs
pending[:0] = tparts
else:
resolved.append(comp)
return os.path.join(root, *resolved)The patched engine applies _safe_resolve to the parent directories of each member during extraction. If a symbolic link points to an absolute path, the resolved stack is cleared, forcing the path resolution to restart from the container's rootfs. Hard link extraction is also deferred until after all regular files are fully written to avoid race conditions.
Exploitation requires an attacker to supply a crafted tar archive, container image, or backup to a victim who then runs proot-distro install or proot-distro restore with the malicious input. No special privileges are required.
When the victim runs the installation command, the symlink is written to disk. The subsequent file member is then written through the symlink, placing a payload inside the host's terminal configuration. The payload executes the next time the victim opens a Termux shell session.
The vulnerability has been assigned a CVSS v3.1 score of 8.2 (CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:N). The scope metric is set to Changed (S:C) because the exploit bypasses the container runtime boundaries to alter files on the host system.
The concrete impact is dictated by the privileges of the executing process. In Termux, which runs within a single Android user context, an attacker can modify local shell environment files, compromising the terminal session and potentially accessing stored keys or credentials. In general Linux systems, running the extraction process as root allows the attacker to compromise the entire operating system by writing to /etc/shadow or creating systemd services.
To address this vulnerability, users must upgrade to proot-distro version 5.1.5 or later. The update introduces the _safe_resolve logic to trap symlinks inside the container's root directory.
If upgrading is not immediately possible, users should enforce the following temporary workarounds:
Avoid installing or restoring container archives from unverified or third-party sources.
Avoid running proot-distro operations as the root user.
Use tar -tvf <archive> to inspect the contents of any external archive and verify that it does not contain absolute symlinks or suspicious targets prior to installation.
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
proot-distro Termux | < 5.1.5 | 5.1.5 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-59 (Improper Link Resolution Before File Access) |
| Attack Vector | Local (AV:L) |
| CVSS Score | 8.2 |
| Exploit Status | Proof of Concept available |
| KEV Status | Not listed |
| Affected Product | proot-distro |
| Fixed Version | 5.1.5 |
The product exposes a vulnerability where it does not properly limit the resolution of symbolic links, allowing users to read or write files outside the intended boundaries.
CVE-2026-59944 is a path traversal and link-following vulnerability in Composer, the PHP dependency manager. This flaw allows malicious or compromised packages to bypass previous path-hardening protections and perform arbitrary filesystem operations outside of their designated installation directory, leading to unauthorized permission modifications or execution proxy creations.
A critical Broken Object Level Authorization (BOLA) vulnerability was identified in Trigger.dev before version v4.5.2. An authenticated attacker could trigger a run replay and supply an arbitrary target environmentId belonging to a completely different tenant. Because the server failed to validate whether the target environment belonged to the same project or organization as the source run, it would execute the task within the victim's environment, resulting in unauthorized cross-tenant write operations and remote task execution.
A critical Server-Side Request Forgery (SSRF) vulnerability in Trigger.dev prior to version 4.5.2 allows authenticated organization members to configure webhook alert channels with unvalidated target URLs. This can lead to internal network scanning and cloud metadata extraction.
A Server-Side Request Forgery (SSRF) vulnerability exists in the rmcp OAuth client, which is part of the Model Context Protocol (MCP) Rust SDK. The vulnerability arises from insecure processing of the resource_metadata parameter in WWW-Authenticate headers returned by a malicious or compromised MCP server. The client parses and fetches absolute URLs from this header without validation of scheme, origin, or network routing, allowing remote attackers to initiate HTTP GET requests to local network interfaces, RFC 1918 private subnets, or cloud metadata endpoints.
A module allowlist bypass vulnerability (CVE-2026-92945 / GHSA-7q3f-wx44-378m) was identified in the vm2 sandboxing library prior to version 3.11.7. This flaw permits unauthenticated or untrusted code running within the sandbox environment to bypass explicit module restrictions. When the transitive resolution option is disabled, the system fails to validate file system path boundaries, allowing prefix-sharing sibling directories to be resolved and loaded, thereby escaping intended sandbox restrictions.
CVE-2026-92941 is a critical sandbox-escape and trust-manipulation vulnerability in the vm2 library (versions 3.11.3 to 3.11.6). This security flaw allows untrusted code executing within a NodeVM sandbox environment to compromise the global TLS trust store of the host Node.js process. By leveraging a design flaw where the host's native 'tls.setDefaultCACertificates' can be executed via a proxy wrapper, combined with a bridge unwrapping bypass in the 'url' module, an attacker can modify the process-wide default root Certificate Authorities. Consequently, all subsequent outbound TLS/HTTPS clients running on the host thread are forced to trust attacker-signed certificates, facilitating transparent Man-in-the-Middle (MitM) attacks. The vulnerability was resolved in version 3.11.7 of vm2 by introducing built-in member-level sanitization before applying read-only proxy wrappers.