Skip to content

v0.17.8: path traversal fix in dataset archive extraction

Latest

Choose a tag to compare

@w4nderlust w4nderlust released this 27 Jul 00:35

Security fix

This release fixes a path traversal in dataset archive extraction (ludwig/datasets/archives.py). Anyone who extracts tar archives from sources they do not fully control should upgrade.

What was wrong

extract_archive() validated that every tar member name resolved inside the destination directory, then called extractall(). That validation did not inspect link members, so it could be bypassed.

An archive containing a symlink pointing outside the destination, followed by a regular file whose name resolves through that symlink, passed validation: at check time the symlink does not exist yet, and both member names look like they land inside the destination. extractall() then created the link and wrote through it, placing archive-controlled content at an arbitrary path with the privileges of the extracting process.

A second, separate issue in the same containment check: it used os.path.commonprefix, which compares characters rather than path components, so a destination of /data/dest also accepted /data/dest-evil as being inside it.

Affected on Python 3.12 and 3.13, which is the range Ludwig supports. Python 3.14 was not affected, because TarFile.extractall() there already defaults to filter="data".

What changed

  • Link targets are now validated in addition to member names, for both symlinks and hard links
  • extractall() is called with filter="data", which independently refuses escaping links on 3.12 and 3.13
  • The containment check uses os.path.commonpath instead of os.path.commonprefix
  • Extraction failures now raise a typed UnsafeArchiveError rather than a bare Exception
  • Added regression tests covering symlink, hard link, absolute path, parent traversal, and sibling directory escapes

Credit

Reported by Udit Jain, who found the issue, verified it against the shipped code, and offered coordinated disclosure. Thank you.

Private Vulnerability Reporting is now enabled on this repository, and there is a SECURITY.md describing how to report future issues.

Full changelog: v0.17.7...v0.17.8