pypa/pip · critical · InstallationError
Invalid member in the tar file
Error message
Invalid member in the tar file {}: {} What it means
Raised as InstallationError by untar_file's pip_filter (unpacking.py:238) when a tar archive member fails the data_filter extraction safety check. Python 3.12+'s tarfile.data_filter (PEP 706) blocks dangerous entries: absolute paths, path traversal (../), hardlinks/symlinks pointing outside the destination, device files, etc. pip wraps the filter to also apply executable permissions; any TarError from the filter is re-raised as InstallationError with the member and error detail.
Solutions
- Verify the package source is trusted and re-download from the official index to rule out corruption.
- Report the package to PyPI / the maintainer if it contains entries that trip the safety filter — it may be malicious or buggy.
- Avoid installing from untrusted direct-URL tarballs; use wheels from vetted indices when available.
- If you maintain the package, rebuild the sdist ensuring all members are relative paths without symlinks escaping the archive root.
Defensive patterns
Strategy: validation
Validate before calling
import tarfile, os
def check_tar_for_unsafe_members(tar_path: str, dest: str) -> list[str]:
"""Return list of unsafe tar members using the data_filter."""
dest = os.path.abspath(dest)
unsafe = []
with tarfile.open(tar_path) as tf:
for member in tf.getmembers():
try:
tarfile.data_filter(member, dest)
except (tarfile.TarError, ValueError) as e:
unsafe.append(f'{member.name}: {e}')
return unsafe Type guard
import tarfile
def is_safe_tar_member(member: tarfile.TarInfo, dest: str) -> bool:
"""True if the tar member passes the PEP 706 data_filter."""
try:
tarfile.data_filter(member, dest)
return True
except tarfile.TarError:
return False Try / catch
from pip._internal.exceptions import InstallationError
try:
# untar / install sdist operation
pass
except InstallationError as e:
if 'Invalid member in the tar file' in str(e):
# Unsafe tar entry detected: do NOT extract; report as security issue
pass Prevention
- Only install sdists from trusted sources — prefer wheels from vetted indices.
- Pre-scan downloaded tarballs with tarfile.data_filter before extraction.
- Keep Python updated to get the latest tarfile security fixes (PEP 706).
- Treat tar-slip detection as a security incident and report the package upstream.
When it happens
Trigger: During installation of a sdist tarball, untar_file calls tar.extractall with pip_filter at line 254. The filter calls data_filter(member, location) at line 219; if the member is unsafe (traversal, absolute path, dangerous link), a TarError is raised and caught at line 234, then re-raised as InstallationError at 238. There is a special case (lines 220-233) that downgrades LinkOutsideDestinationError to tar_filter on specific buggy Python patch versions.
Common situations: A malicious or malformed sdist tarball containing entries that try to write outside the target directory. A tarball built on a system with absolute paths or symlinks that the filter considers unsafe. A corrupted or partially-downloaded archive.
Related errors
- The tar file ( ) has a file ( ) trying to install outside…
- The zip file ( ) has a file ( ) trying to install outside…
- Invalid script entry point name
- path outside destination: %r
- Path in pylock file obtained from a URL resolves outside…
AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08).
Data as JSON: /api/errors/40a0972a1163f806.
Report an issue: GitHub.
Appendix: 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 f399c37189)