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

  1. Verify the package source is trusted and re-download from the official index to rule out corruption.
  2. Report the package to PyPI / the maintainer if it contains entries that trip the safety filter — it may be malicious or buggy.
  3. Avoid installing from untrusted direct-URL tarballs; use wheels from vetted indices when available.
  4. 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

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


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)