pypa/pip · error · InstallationError

Absolute paths are not supported in pylock files obtained…

Error message

Absolute paths are not supported in pylock files obtained from a URL: {path!r} in {pylock_path_or_url!r}

What it means

Raised as InstallationError by _package_dist_url (pylock.py:179) when a pylock file loaded from a URL contains an absolute filesystem path in a package's path field. Absolute paths in a remote lock file are a security risk: they could reference arbitrary local files on the machine running pip (e.g. /etc/shadow). The code checks _is_url(pylock_path_or_url) at line 178 and rejects absolute paths at 179. Local (non-URL) pylock files are allowed to use absolute paths.

Solutions

  1. Use relative paths in the pylock file so they resolve against the lock file's URL base.
  2. If you control the packages, set the url field (a proper download URL) instead of the path field for remote lock files.
  3. Download the pylock file and use it from a local path instead of a URL, which allows absolute paths.
  4. Regenerate the lock file from scratch on the target system so paths are local and relative.

Example fix

// before (remote pylock.toml)
[[packages]]
name = "pkg"
path = "/home/user/wheels/pkg.whl"

// after (remote pylock.toml)
[[packages]]
name = "pkg"
url = "https://index.example.com/wheels/pkg.whl"
Defensive patterns

Strategy: validation

Validate before calling

import os

def find_absolute_paths_in_remote_pylock(toml_content: str, is_url: bool) -> list[str]:
    """Find absolute paths in a pylock file loaded from a URL."""
    if not is_url:
        return []  # local pylock files allow absolute paths
    import re
    # Naive check for path = "/abs/path" patterns
    return re.findall(r'path\s*=\s*["\']?(/[^"\']+)["\']?', toml_content)

Type guard

import os

def is_safe_pylock_path_field(path: str, pylock_is_url: bool) -> bool:
    """True if the path field is safe given the lock file source."""
    if os.path.isabs(path):
        return not pylock_is_url  # absolute paths only OK for local lock files
    return True

Prevention

When it happens

Trigger: Loading a pylock.toml from http(s):// or file:// URL that has a package entry with path="/some/abs/path" or path="C:\\path". The os.path.isabs check at line 156 passes, then the URL check at 178 triggers the raise.

Common situations: A lock file generated on one machine that embedded absolute build paths and is then distributed via a URL. Lock files created by a CI system that recorded container/runner absolute paths. Copying a local lock file to a web server without sanitising paths.

Related errors


AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08). Data as JSON: /api/errors/6625caebbb65bf20. Report an issue: GitHub.

Appendix: source

Thrown at src/pip/_internal/utils/pylock.py:179

                # "file:..." as absolute, so it reaches here and urljoin honors
                # its scheme, discarding the pylock base. Only keep the result
                # if its scheme and host still match the lock's own.
                base = urlsplit(pylock_path_or_url)
                target = urlsplit(dist_url)
                if (target.scheme, target.netloc) != (base.scheme, base.netloc):
                    raise InstallationError(
                        f"Path {path!r} in pylock file obtained from a URL "
                        f"resolves outside its location: {pylock_path_or_url!r}"
                    )
                return dist_url
            else:
                return path_to_url(
                    os.path.join(os.path.dirname(pylock_path_or_url), path)
                )
        else:
            # absolute path, reject if pylock comes from a URL
            if _is_url(pylock_path_or_url):
                raise InstallationError(
                    f"Absolute paths are not supported in pylock files obtained "
                    f"from a URL: {path!r} in {pylock_path_or_url!r}"
                )
            return path_to_url(path)
    else:
        assert url is not None  # guaranteed by packaging.pylock validation
        return url


def package_vcs_requirement_url(
    pylock_path_or_url: str, package_vcs: PackageVcs
) -> str:
    dist_url = _package_dist_url(pylock_path_or_url, package_vcs.path, package_vcs.url)
    url = f"{package_vcs.type}+{dist_url}@{package_vcs.commit_id}"
    if package_vcs.subdirectory:
        if "#" in url:
            raise InstallationError(
                f"Package URL {url!r} cannot contain fragments in combination "

View on GitHub (pinned to f399c37189)