# pyLoad: Tar extraction creates device nodes and FIFOs (member types not filtered; tarfile extractall without filter=)

pyLoad's tar hardening validated member names and link targets but not member types, so a crafted tar creates device nodes and FIFOs, giving root disk access.

- Payout: Research
- Severity: high
- Program: pyLoad
- Found by: skeletonsec
- Disclosed: 2026-10-09
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-fr26-jjhm-638c
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-fr26-jjhm-638c
- Tags: area:web domain:web impact:dos impact:integrity impact:privesc kind:research platform:ghsa sev:high tech:python technique:incomplete-fix technique:source-review vuln:misconfiguration vuln:path-traversal

**Target:** pyLoad archive extractor (UnTar._safe_extractall) via API add_package/service_call
**Root cause:** The GHSA-mvwx-582f-56r7 fix only checked member names and symlink/hardlink targets, never member types, and called tarfile.extractall without filter=; on Python <3.14 the default fully_trusted filter honors mknod for euid=0 and creates FIFOs for any euid.
**Steps:**
1. Craft a tar named *.bin (so UnTar content-sniffs it) containing a regular marker.txt, a CHRTYPE member `nulldev` with devmajor=1 devminor=3 mode=0o666, and a FIFOTYPE member `pipe`
2. As a low-priv user, POST `/api/add_package` with `{"name":"poc","links":["http://x/dev.bin"],"dest":1}` and place the archive in the package download folder
3. POST `/api/service_call` with `{"service_name":"ExtractArchive.extract_package","arguments":["<pid>"]}`
4. Observe `crw-rw-rw- 1 root root 1, 3 nulldev` and `prw-r--r-- 1 root root pipe` in the extract dir
5. Negative control: a `../evil` traversal member is rejected with `ArchiveError: Attempted path traversal in archive`
**How found:** Reviewed the prior GHSA-mvwx-582f-56r7 hardening in `_safe_extractall` and noticed the loop only inspects names and link targets, then checked Python tarfile filter semantics across 3.9–3.13 to confirm special member types are honored.
**Exploitation:** Any low-privileged authenticated user with ADD/STATUS rights supplies a crafted archive and triggers ExtractArchive.extract_package; when pyLoad runs as root (official Docker image), the created block/character device node grants raw disk read/write and host compromise, and FIFOs enable process hangs or IPC confusion.
**Escalation:** Root-run pyLoad turns a character/block device node into raw host disk access; non-root deployments still get FIFOs and node entries in user-accessible trees.
**Insight:** When auditing a prior path-traversal fix, enumerate every attribute of the archive member object the fix ignores — type, mode, devmajor/devminor, uid/gid — and check the runtime's default extraction filter version, since `filter="data"` only became default in Python 3.14.

