diff --git a/news/10979.bugfix.rst b/news/10979.bugfix.rst new file mode 100644 index 00000000000..930eba31742 --- /dev/null +++ b/news/10979.bugfix.rst @@ -0,0 +1 @@ +Prioritize URL credentials over netrc. diff --git a/src/pip/_internal/network/auth.py b/src/pip/_internal/network/auth.py index ca42798bd95..e40ebfb2785 100644 --- a/src/pip/_internal/network/auth.py +++ b/src/pip/_internal/network/auth.py @@ -109,7 +109,8 @@ def _get_index_url(self, url: str) -> Optional[str]: def _get_new_credentials( self, original_url: str, - allow_netrc: bool = True, + *, + allow_netrc: bool = False, allow_keyring: bool = False, ) -> AuthInfo: """Find and return credentials for the specified URL.""" @@ -260,7 +261,7 @@ def handle_401(self, resp: Response, **kwargs: Any) -> Response: # Query the keyring for credentials: username, password = self._get_new_credentials( resp.url, - allow_netrc=False, + allow_netrc=True, allow_keyring=True, ) diff --git a/tests/functional/test_install_config.py b/tests/functional/test_install_config.py index 2e4bb742785..c90be5bb4da 100644 --- a/tests/functional/test_install_config.py +++ b/tests/functional/test_install_config.py @@ -415,3 +415,46 @@ def get_credential(url, username): assert "get_credential was called" in result.stderr else: assert "get_credential was called" not in result.stderr + + +def test_prioritize_url_credentials_over_netrc( + script: PipTestEnvironment, + data: TestData, + cert_factory: CertFactory, +) -> None: + cert_path = cert_factory() + ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23) + ctx.load_cert_chain(cert_path, cert_path) + ctx.load_verify_locations(cafile=cert_path) + ctx.verify_mode = ssl.CERT_REQUIRED + + server = make_mock_server(ssl_context=ctx) + server.mock.side_effect = [ + package_page( + { + "simple-3.0.tar.gz": "/files/simple-3.0.tar.gz", + } + ), + authorization_response(str(data.packages / "simple-3.0.tar.gz")), + ] + + url = f"https://USERNAME:PASSWORD@{server.host}:{server.port}/simple" + + netrc = script.scratch_path / ".netrc" + netrc.write_text( + f"machine {server.host} login wrongusername password wrongpassword" + ) + with server_running(server): + script.environ["NETRC"] = netrc + script.pip( + "install", + "--no-cache-dir", + "--index-url", + url, + "--cert", + cert_path, + "--client-cert", + cert_path, + "simple", + ) + script.assert_installed(simple="3.0")