pypa/pip · critical · InstallationError
Invalid member in the tar file {}: {}
Error message
Invalid member in the tar file {}: {} What it means
InstallationError raised when extracting a tar archive and the underlying Python tarfile filter raises a TarError (e.g. a member that the data_filter rejects for safety). pip's pip_filter wraps the member extraction; any tarfile.TarError propagates as this user-facing message identifying the archive and the offending member. It is the tar equivalent of the zip path-traversal guard but covers all data_filter violations.
Source
Thrown at src/pip/_internal/utils/unpacking.py:238
except tarfile.LinkOutsideDestinationError:
if sys.version_info[:3] in {
(3, 9, 17),
(3, 10, 12),
(3, 11, 4),
}:
# The tarfile filter in specific Python versions
# raises LinkOutsideDestinationError on valid input
# (https://github.com/python/cpython/issues/107845)
# Ignore the error there, but do use the
# more lax `tar_filter`
member = tarfile.tar_filter(member, location)
else:
raise
except tarfile.TarError as exc:
message = "Invalid member in the tar file {}: {}"
# Filter error messages mention the member name.
# No need to add it here.
raise InstallationError(
message.format(
filename,
exc,
)
)
if member.isfile() and orig_mode & 0o111:
member.mode = default_mode_plus_executable
else:
# See PEP 706 note above.
# The PEP changed this from `int` to `Optional[int]`,
# where None means "use the default". Mypy doesn't
# know this yet.
member.mode = None # type: ignore [assignment]
return member
tar.extractall(location, filter=pip_filter)
finally:View on GitHub (pinned to d7d0d0a394)
Solutions
- Inspect the tar with `tar -tvf file.tar.gz` and locate the offending member named in the error.
- Reject and re-download from a trusted source; verify the hash.
- If legitimately benign, rebuild the archive without the offending member.
- Keep pip current so its data_filter rules match upstream CPython.
Example fix
// before
untar_file('pkg.tar.gz', '/target') # contains a device node / absolute path
// after
# rebuild the archive with safe members:
tar --sort=name --mtime='UTC 1970-01-01' -czf pkg.tar.gz -C src . Defensive patterns
Strategy: validation
Validate before calling
import tarfile
def tar_is_safe(path: str) -> bool:
try:
with tarfile.open(path) as t:
for m in t.getmembers():
if m.name.startswith('/') or '..' in m.name.split('/'):
return False
if m.issym() or m.islnk():
if m.linkname.startswith('/') or '..' in m.linkname.split('/'):
return False
return True
except tarfile.TarError:
return False Type guard
null
Try / catch
null
Prevention
- Run on Python 3.12+ so pip uses tarfile.data_filter.
- Verify sdist hashes from the index.
- Reject packages from untrusted mirrors.
- Inspect tar contents in CI before install.
When it happens
Trigger: Unpacking a .tar.gz/.tar.bz2/.tar.xz source distribution where a member triggers tarfile's data_filter rejection (link/absolute path traversal, device files, etc.). Triggered from untar_file's pip_filter on Python 3.12+ (or backported filter).
Common situations: Malicious sdist; legacy tar with absolute paths; tar containing device nodes; older archive created before PEP 706 filtering conventions.
Related errors
- The tar file ({}) has a file ({}) trying to install outside
- Path {path!r} in pylock file obtained from a URL resolves ou
- The zip file ({}) has a file ({}) trying to install outside
- path outside destination: %r
- Invalid script entry point name {entry.name!r}: the script w
AI-assisted analysis of pypa/pip@d7d0d0a394 (2026-08-04).
Data as JSON: /data/errors/40a0972a1163f806.json.
Report an issue: GitHub.