{"record":{"id":"a4445e448418a27c","repo":"pypa/pip","slug":"path-is-a-symlink-will-not-return-uid-for-symli","errorCode":null,"errorMessage":"{path} is a symlink; Will not return uid for symlinks","messagePattern":"(.+?) is a symlink; Will not return uid for symlinks","errorType":"exception","errorClass":"OSError","httpStatus":null,"severity":"warning","filePath":"src/pip/_internal/utils/compat.py","lineNumber":66,"sourceCode":"        https://github.com/pypa/pip/pull/935#discussion_r5307003\n\n    Placed this function in compat due to differences on AIX and\n    Jython, that should eventually go away.\n\n    :raises OSError: When path is a symlink or can't be read.\n    \"\"\"\n    if hasattr(os, \"O_NOFOLLOW\"):\n        fd = os.open(path, os.O_RDONLY | os.O_NOFOLLOW)\n        file_uid = os.fstat(fd).st_uid\n        os.close(fd)\n    else:  # AIX and Jython\n        # WARNING: time of check vulnerability, but best we can do w/o NOFOLLOW\n        if not os.path.islink(path):\n            # older versions of Jython don't have `os.fstat`\n            file_uid = os.stat(path).st_uid\n        else:\n            # raise OSError for parity with os.O_NOFOLLOW above\n            raise OSError(f\"{path} is a symlink; Will not return uid for symlinks\")\n    return file_uid\n\n\n# The importlib.resources.open_text function was deprecated in 3.11 with suggested\n# replacement we use below.\nif sys.version_info < (3, 11):\n    open_text_resource = importlib.resources.open_text\nelse:\n\n    def open_text_resource(\n        package: str, resource: str, encoding: str = \"utf-8\", errors: str = \"strict\"\n    ) -> IO[str]:\n        return (importlib.resources.files(package) / resource).open(\n            \"r\", encoding=encoding, errors=errors\n        )\n\n\nif sys.version_info >= (3, 11):","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/pypa/pip/blob/f399c3718970b1b0e2478dac5296eb62679a9b86/src/pip/_internal/utils/compat.py#L48-L84","documentation":"Raised as OSError by get_socket_standard_paths / get_uid_compat when the given path is a symlink and the OS lacks os.O_NOFOLLOW (only AIX and Jython fall into this branch). The function intentionally refuses to resolve symlinks to prevent time-of-check-time-of-use (TOCTOU) attacks: returning a uid for a symlink would let an attacker swap the target after the check. On mainstream platforms with O_NOFOLLOW the open itself fails on symlinks, so this explicit raise is the fallback path for parity.","triggerScenarios":"Calling the internal get_uid helper on a system without os.O_NOFOLLOW (AIX, old Jython) where the target path is a symbolic link. The code at compat.py:61 checks os.path.islink and raises at line 66.","commonSituations":"Running pip on AIX where the Python stdlib path or a package cache entry is a symlink. Legacy Jython environments. A filesystem where pip's temporary directories or wheel cache contain symlinks created by a package manager or mount point.","solutions":["Remove the symlink so the path points to a regular file or directory.","Run pip on a mainstream CPython build that supports os.O_NOFOLLOW (Linux, macOS, Windows) instead of AIX/Jython.","If the symlink is intentional and trusted, resolve it to its real target before invoking pip and pass the canonical path.","Report an upstream issue if pip itself created the symlink in its cache directory."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"import os\n\ndef safe_uid_path(path: str) -> str | None:\n    \"\"\"Return a non-symlink path or None if it is a symlink.\"\"\"\n    if os.path.islink(path):\n        return None  # caller should resolve or reject\n    return path\n\n# Before calling pip on a path, ensure it's not a symlink:\n# resolved = os.path.realpath(path)","typeGuard":"import os\n\ndef is_safe_for_uid(path: str) -> bool:\n    \"\"\"True if the path is not a symlink (safe for uid lookup on AIX/Jython).\"\"\"\n    return not os.path.islink(path)","tryCatchPattern":null,"preventionTips":["Resolve symlinks with os.path.realpath before pointing pip at directories.","On AIX/Jython, prefer mainstream CPython if O_NOFOLLOW support is critical.","Avoid creating symlinks inside pip's cache or build directories."],"tags":["security","symlink","aix","jython","toctou"],"backgroundTag":null,"analyzedSha":"f399c3718970b1b0e2478dac5296eb62679a9b86","analyzedAt":"2026-08-08T23:01:42.227Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}