URL.__repr__: mask the password component so repr() does not leak credentials into logs#1793
Open
HrachShah wants to merge 1 commit into
Open
URL.__repr__: mask the password component so repr() does not leak credentials into logs#1793HrachShah wants to merge 1 commit into
HrachShah wants to merge 1 commit into
Conversation
…dentials into logs str() still surfaces the real password for callers that explicitly opted in; only the auto-rendered repr() used by logs, tracebacks, and debuggers is masked. The marker length matches the password length so the redacted URL keeps a stable width regardless of password value. Closes aio-libs#1629.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
URL.__repr__currently embeds the raw password component from the URL'suserinfo (when present), so any time a
URLinstance is rendered throughrepr()(logging frameworks, REPL sessions, exception tracebacks) thecredentials flow through:
This is a common source of credential leakage in operational settings:
an exception bubbled up through an HTTP client, an interactive debugger,
or a JSON dump of context all surface the password.
The fix replaces the password in
__repr__with a fixed redaction markerwhose length matches the original password, so a redacted
URL('https://user:******@example.com')keeps a stable width regardless of passwordvalue (handy for log diffing) but does not reveal anything about the
password itself.
Changes
yarl/_url.py: add a_URL_REPR_PASSWORD_MASKconstant and a_repr_str()helper.__repr__now uses_repr_str()which rebuildsthe netloc with the password replaced by the marker of equal length.
When
raw_passwordisNone(the common case), it just returnsstr(self)so the no-credentials path keeps its existing behavior andno string is allocated for the masked form.
tests/test_url.py: newtest_repr_masks_passwordcoveringuser+password, empty-user+password, empty-password (no-op), plain URL
(no-op), and a percent-encoded password. The test also pins the
behavior that
str()is unchanged so the new masking inrepr()isstrictly opt-out for callers that really want to see the password.
Verification
python -m pytest tests/ -o "addopts=" --timeout=60 -qreports1455 passed, 101 skipped, 4 xfailed(4 xfailed are pre-existing andunrelated to this change).
test_repr_masks_passwordis the only new test, and itfails on the unpatched code (regr test covers the regression).
Migration impact
__repr__is documented as "for developers" and is allowed to changeacross releases. The string returned by
str(URL)is unchanged, soserialization paths and any code that explicitly renders a URL through
str()keep working as before.Refs: #1629.