Skip to content

Commit

Permalink
Redact URLs in Collecting... logs
Browse files Browse the repository at this point in the history
  • Loading branch information
sbidoul committed Oct 14, 2023
1 parent 2333ef3 commit 8f0ed32
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 2 deletions.
1 change: 1 addition & 0 deletions news/12350.bugfix.rst
@@ -0,0 +1 @@
Redact password from URLs in some additional places.
3 changes: 2 additions & 1 deletion src/pip/_internal/operations/prepare.py
Expand Up @@ -47,6 +47,7 @@
display_path,
hash_file,
hide_url,
redact_auth_from_requirement,
)
from pip._internal.utils.temp_dir import TempDirectory
from pip._internal.utils.unpacking import unpack_file
Expand Down Expand Up @@ -277,7 +278,7 @@ def _log_preparing_link(self, req: InstallRequirement) -> None:
information = str(display_path(req.link.file_path))
else:
message = "Collecting %s"
information = str(req.req or req)
information = redact_auth_from_requirement(req.req) if req.req else str(req)

# If we used req.req, inject requirement source if available (this
# would already be included if we used req directly)
Expand Down
3 changes: 2 additions & 1 deletion src/pip/_internal/req/req_install.py
Expand Up @@ -49,6 +49,7 @@
display_path,
hide_url,
is_installable_dir,
redact_auth_from_requirement,
redact_auth_from_url,
)
from pip._internal.utils.packaging import safe_extra
Expand Down Expand Up @@ -188,7 +189,7 @@ def __init__(

def __str__(self) -> str:
if self.req:
s = str(self.req)
s = redact_auth_from_requirement(self.req)
if self.link:
s += " from {}".format(redact_auth_from_url(self.link.url))
elif self.link:
Expand Down
8 changes: 8 additions & 0 deletions src/pip/_internal/utils/misc.py
Expand Up @@ -35,6 +35,7 @@
cast,
)

from pip._vendor.packaging.requirements import Requirement
from pip._vendor.pyproject_hooks import BuildBackendHookCaller
from pip._vendor.tenacity import retry, stop_after_delay, wait_fixed

Expand Down Expand Up @@ -578,6 +579,13 @@ def redact_auth_from_url(url: str) -> str:
return _transform_url(url, _redact_netloc)[0]


def redact_auth_from_requirement(req: Requirement) -> str:
"""Replace the password in a given requirement url with ****."""
if not req.url:
return str(req)
return str(req).replace(req.url, redact_auth_from_url(req.url))


class HiddenText:
def __init__(self, secret: str, redacted: str) -> None:
self.secret = secret
Expand Down
26 changes: 26 additions & 0 deletions tests/unit/test_utils.py
Expand Up @@ -14,6 +14,7 @@
from unittest.mock import Mock, patch

import pytest
from pip._vendor.packaging.requirements import Requirement

from pip._internal.exceptions import HashMismatch, HashMissing, InstallationError
from pip._internal.utils.deprecation import PipDeprecationWarning, deprecated
Expand All @@ -37,6 +38,7 @@
normalize_path,
normalize_version_info,
parse_netloc,
redact_auth_from_requirement,
redact_auth_from_url,
redact_netloc,
remove_auth_from_url,
Expand Down Expand Up @@ -765,6 +767,30 @@ def test_redact_auth_from_url(auth_url: str, expected_url: str) -> None:
assert url == expected_url


@pytest.mark.parametrize(
"req, expected",
[
("pkga", "pkga"),
(
"resolvelib@ "
" git+https://test-user:test-pass@github.com/sarugaku/resolvelib@1.0.1",
"resolvelib@"
" git+https://test-user:****@github.com/sarugaku/resolvelib@1.0.1",
),
(
"resolvelib@"
" git+https://test-user:test-pass@github.com/sarugaku/resolvelib@1.0.1"
" ; python_version>='3.6'",
"resolvelib@"
" git+https://test-user:****@github.com/sarugaku/resolvelib@1.0.1"
' ; python_version >= "3.6"',
),
],
)
def test_redact_auth_from_requirement(req: str, expected: str) -> None:
assert redact_auth_from_requirement(Requirement(req)) == expected


class TestHiddenText:
def test_basic(self) -> None:
"""
Expand Down

0 comments on commit 8f0ed32

Please sign in to comment.