Skip to content

Commit 78c597d

Browse files
committed
git: ignore http auth for ssh url
This change ensures that http-basic auth credentials are only passed to dulwich when the remote url uses http/https schemes. In addition to the above, it is now ensured that username/password parameters are not passed through to dulwich unless both username and password are configured explicitly. This is to ensure that dulwich does not bail out if it detects a username in the url (eg: `ssh://[email protected]`).
1 parent bb7b32e commit 78c597d

File tree

4 files changed

+37
-1
lines changed

4 files changed

+37
-1
lines changed

src/poetry/utils/authenticator.py

+5
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,11 @@ def _get_credentials_for_url(
270270
return credential
271271

272272
def get_credentials_for_git_url(self, url: str) -> HTTPAuthCredential:
273+
parsed_url = urllib.parse.urlsplit(url)
274+
275+
if parsed_url.scheme not in {"http", "https"}:
276+
return HTTPAuthCredential()
277+
273278
key = f"git+{url}"
274279

275280
if key not in self._credentials:

src/poetry/vcs/git/backend.py

+9-1
Original file line numberDiff line numberDiff line change
@@ -186,9 +186,17 @@ def _fetch_remote_refs(cls, url: str, local: Repo) -> FetchPackResult:
186186
client: GitClient
187187
path: str
188188

189+
kwargs: dict[str, str] = {}
189190
credentials = get_default_authenticator().get_credentials_for_git_url(url=url)
191+
192+
if credentials.password and credentials.username:
193+
# we do this conditionally as otherwise, dulwich might complain if these
194+
# parameters are passed in for an ssh url
195+
kwargs["username"] = credentials.username
196+
kwargs["password"] = credentials.password
197+
190198
client, path = get_transport_and_path( # type: ignore[no-untyped-call]
191-
url, username=credentials.username, password=credentials.password
199+
url, **kwargs
192200
)
193201

194202
with local:

tests/integration/test_utils_vcs_git.py

+19
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,25 @@ def test_configured_repository_http_auth(
298298
spy_get_transport_and_path.assert_called_once()
299299

300300

301+
def test_username_password_parameter_is_not_passed_to_dulwich(
302+
mocker: MockerFixture, source_url: str, config: Config
303+
) -> None:
304+
from poetry.vcs.git import backend
305+
306+
spy_clone = mocker.spy(Git, "_clone")
307+
spy_get_transport_and_path = mocker.spy(backend, "get_transport_and_path")
308+
309+
with Git.clone(url=source_url, branch="0.1") as repo:
310+
assert_version(repo, BRANCH_TO_REVISION_MAP["0.1"])
311+
312+
spy_clone.assert_called_once()
313+
314+
spy_get_transport_and_path.assert_called_with(
315+
location=source_url,
316+
)
317+
spy_get_transport_and_path.assert_called_once()
318+
319+
301320
def test_system_git_called_when_configured(
302321
mocker: MockerFixture, source_url: str, use_system_git_client: None
303322
) -> None:

tests/utils/test_authenticator.py

+4
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,10 @@ def test_authenticator_git_repositories(
592592
assert two.username == "baz"
593593
assert two.password == "qux"
594594

595+
two_ssh = authenticator.get_credentials_for_git_url("ssh://[email protected]/org/two.git")
596+
assert not two_ssh.username
597+
assert not two_ssh.password
598+
595599
three = authenticator.get_credentials_for_git_url("https://foo.bar/org/three.git")
596600
assert not three.username
597601
assert not three.password

0 commit comments

Comments
 (0)