T09 · Insecure Skill Coding Practices
- Location
scripts/extract.py:130- Finding
Unsafe TAR Extraction on Supported Legacy Python Versions
- Content
View full analysis
Vulnerability Details
File Location:
scripts/extract.py, lines 130-138
Vulnerability Type: Path traversal and unsafe link extraction
Risk Level: HighVulnerable Code
python def _safe_tar_extract(tf: tarfile.TarFile, dest: Path) -> None: """Use 'data' filter on Python 3.12+ for security; fall back gracefully.""" if hasattr(tarfile, "data_filter"): try: tf.extractall(dest, filter="data") return except TypeError: pass tf.extractall(dest)Technical Analysis
The project advertises compatibility with Python 3.8 and later, but safe TAR filtering is only used when
tarfile.data_filteris available. On older supported runtimes, or if the filtered call raisesTypeError, execution falls back to unrestrictedTarFile.extractall().An attacker-controlled TAR can contain absolute paths, names containing parent-directory components, or unsafe symbolic and hard links. Without explicit member and link-target validation, extraction may place or overwrite files outside the intended output directory. The exploit does not require command injection; it abuses archive metadata interpreted by the TAR extraction implementation.
Attack Path
- An attacker prepares a TAR archive containing traversal paths or unsafe links that resolve outside the extraction directory.
- The archive is supplied to a user or agent that invokes this skill on a Python runtime where the
datafilter is unavailable or not accepted. _safe_tar_extract()reaches the unfilteredtf.extractall(dest)fallback.- Malicious members are written outside
dest, subject to the filesystem permissions of the running process. - The attacker may overwrite application configuration, user files, scripts, or other writable targets.
Impact Assessment
Successful exploitation permits arbitrary file creation or overwrite anywhere writable by the skill proces ...[truncated 277 chars]
- Remediation
View remediation
Remediation Suggestions
- Do not fall back to unrestricted
extractall()on supported legacy runtimes. - Resolve and validate every member destination before extraction, ensuring it remains beneath the resolved output directory.
- Reject absolute paths, drive-qualified paths, parent-directory traversal, device entries, FIFOs, and unsafe symbolic or hard links.
- Validate link targets independently rather than validating only the archive member name.
- Prefer requiring a Python runtime with secure TAR filtering and fail closed if the filter cannot be applied.
- Extract into a newly created isolated directory and remove it on any validation or extraction failure.
- Add regression tests using absolute-path, traversal, symlink, and hard-link archive fixtures.
- Do not fall back to unrestricted
