Skip to content

fix(auth): write PIPENV_PYPI_MIRROR credentials to resolver netrc (#6677)#6678

Open
matteius wants to merge 3 commits into
mainfrom
fix/6677-pypi-mirror-netrc-auth
Open

fix(auth): write PIPENV_PYPI_MIRROR credentials to resolver netrc (#6677)#6678
matteius wants to merge 3 commits into
mainfrom
fix/6677-pypi-mirror-netrc-auth

Conversation

@matteius
Copy link
Copy Markdown
Member

@matteius matteius commented Jun 5, 2026

Problem

Fixes #6677. Since v2026.6.0, pipenv install fails with ResolutionFailure: No matching distribution found when a private index is configured via PIPENV_PYPI_MIRROR with embedded credentials (e.g. https://user:pass@mirror.example.com). The credentials are silently dropped and the index returns 401 Unauthorized.

Root cause

v2026.6.0 shipped the GHSA-8xgg-v3jj-95m2 fix, which stopped placing index credentials on pip's argv (visible via ps//proc/<pid>/cmdline) and instead writes them to a temporary netrc that pip reads.

The regression is an asymmetry in how PIPENV_PYPI_MIRROR is applied:

  • The resolver subprocess (pipenv/resolver.py) prepends a mirror source built from PIPENV_PYPI_MIRROR via replace_pypi_sources(...) — and that mirror URL is where the user's credentials live.
  • The parent process writes the resolver's netrc in _set_resolver_netrc (pipenv/utils/resolver.py) from project.pipfile_sources(), which does not include the mirror substitution.

So the mirror's credentials never reached the netrc. Pip then received the mirror URL with credentials stripped from argv and found no matching netrc entry → 401ResolutionFailure.

This is a different path than #6670 (which handled ${VAR} placeholders in [[source]] URLs and netrc ordering); this one is the PIPENV_PYPI_MIRROR env var being skipped entirely when building the resolver netrc.

Fix

_set_resolver_netrc now applies the same replace_pypi_sources(..., create_mirror_source(...)) substitution the resolver subprocess uses, so the mirror's credentials flow into the netrc again — restoring pre-2026.6.0 behavior without putting secrets back on argv.

Tests

Adds test_set_resolver_netrc_includes_pypi_mirror_credentials, a unit regression test mirroring the issue's config (a custom-host source named pypi with credentials only in PIPENV_PYPI_MIRROR). Full tests/unit/test_credential_safety.py suite passes (17 passed).

Note

The install-time source builder (get_source_list) only substitutes the mirror for pypi.org/simple sources, whereas resolution always prepends it. The canonical authed-mirror case (Pipfile source https://pypi.org/simple + mirror) already gets credentials into the install netrc and works; the reported failure is at resolution, which this fixes. Broadening get_source_list to honor PIPENV_PYPI_MIRROR for arbitrary custom-host sources would be a separate behavior change.

🤖 Generated with Claude Code

matteius and others added 3 commits June 2, 2026 04:31
Signed-off-by: Matt Davis <matteius@gmail.com>
)

The GHSA-8xgg-v3jj-95m2 fix moved index credentials off pip's argv onto a
temporary netrc that pip reads. The resolver subprocess prepends a mirror
source built from PIPENV_PYPI_MIRROR (which is where the user's credentials
live), but the parent wrote the resolver netrc from the un-mirrored
project.pipfile_sources() — so the mirror's credentials were dropped.

Pip then received the mirror URL with credentials stripped from argv and no
matching netrc entry, producing 401 / ResolutionFailure ("No matching
distribution found") for any private index configured via PIPENV_PYPI_MIRROR
with embedded user:pass auth, starting in v2026.6.0.

_set_resolver_netrc now applies the same replace_pypi_sources / mirror
substitution the resolver subprocess uses, so the mirror credentials reach
the netrc again. Adds a unit regression test mirroring the issue's config.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

PIPENV_PYPI_MIRROR with auth no longer working from v2026.6.0

1 participant