T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/archive.py:25
- Finding
- Arbitrary File Write Through Unsafe TAR Archive Extraction## Vulnerability Details **File Location**: `scripts/archive.py`, lines 25-29 **Vulnerability Type**: Path traversal and unsafe link handling during TAR extraction **Risk Level**: High ### Vulnerable Code ```python def extract_tar(filepath, output_dir): """Extract tar/tar.gz/tgz file using Python stdlib""" with tarfile.open(filepath, 'r:*') as tar_ref: tar_ref.extractall(output_dir) return True ``` ### Technical Analysis The application passes every TAR member directly to `tarfile.extractall()` without enforcing a safe extraction filter or validating member paths and link targets. On Python versions where a restrictive extraction filter is not the default, a malicious TAR archive can contain: - Relative traversal paths such as `../../home/user/.config/application.conf` - Absolute paths targeting files outside the selected output directory - Symbolic or hard links that redirect subsequent extraction operations outside the destination - Special files or other unsafe TAR member types Creating `output_dir` before extraction does not constrain archive members to that directory. The destination of every member must be resolved and verified independently. ### Attack Path 1. An attacker creates a TAR, TAR.GZ, TGZ, TAR.BZ2, or TAR.XZ archive containing a member whose path traverses outside the intended extraction directory, or a link that points outside it. 2. The attacker provides the archive to a user or causes an agent to process it. 3. The user or agent runs a command such as: ```bash python3 scripts/archive.py extract malicious.tar -o ./extracted ``` 4. `extract_file()` identifies the input as a TAR archive and calls `extract_tar()`. 5. `tar_ref.extractall(output_dir)` processes the malicious member without an explicitly enforced safe filter. 6. On an affected Python runtime, the crafted member is written outside `./extracted`. ### Impact Assessment The attacker m ...[truncated 675 chars]
- Remediation
- ## Remediation Suggestions On supported Python versions, explicitly require the safe data filter rather than relying on runtime defaults: ```python def extract_tar(filepath, output_dir): destination = Path(output_dir).resolve() destination.mkdir(parents=True, exist_ok=True) with tarfile.open(filepath, "r:*") as tar_ref: tar_ref.extractall(destination, filter="data") return True ``` For compatibility with runtimes that do not support `filter="data"`, implement validation before extraction: 1. Resolve the intended destination directory to an absolute canonical path. 2. Reject absolute member paths. 3. Resolve each member's prospective destination and verify that it remains beneath the extraction directory. 4. Reject traversal components that escape the destination. 5. Reject device files, FIFOs, and other special member types. 6. Reject symbolic and hard links, or separately verify that both their extraction locations and targets remain within the destination. 7. Extract only after all archive members have passed validation. 8. Add regression tests covering absolute paths, `../` traversal, symbolic-link pivots, hard-link pivots, and special files.
