@@ -652,42 +652,60 @@ def expand_path(p: Union[None, PathLike], expand_vars: bool = True) -> Optional[
652652 return None
653653
654654
655+ def _redact_url_credentials (text : str ) -> Optional [str ]:
656+ """Return `text` with the userinfo of a URL redacted, or ``None`` if it has none."""
657+ try :
658+ url = urlsplit (text )
659+ except ValueError :
660+ # This is not a valid URL.
661+ return None
662+ if url .password is None and url .username is None :
663+ return None
664+
665+ # Match urllib.parse's userinfo boundary. Keeping the raw hostinfo
666+ # preserves hostname case, IPv6 brackets, and port formatting.
667+ _ , _ , hostinfo = url .netloc .rpartition ("@" )
668+ redacted = "*****:*****" if url .password is not None else "*****"
669+ return urlunsplit (url ._replace (netloc = f"{ redacted } @{ hostinfo } " ))
670+
671+
655672def remove_password_if_present (cmdline : Sequence [str ]) -> List [str ]:
656673 """Redact credentials in URLs and HTTP Authorization extra headers in a command line.
657674
675+ URLs are also redacted in the key and value of a configuration assignment, such
676+ as ``http.proxy=<url>``. Assignments are recognized in the ``-c <key>=<value>``,
677+ ``-c<key>=<value>``, and ``--config=<key>=<value>`` forms.
678+
658679 If nothing is found, this just returns the command line as-is.
659680
660681 This should be used for every log line that print a command line, as well as
661682 exception messages.
662683 """
663684 new_cmdline = []
664- for index , to_parse in enumerate (cmdline ):
665- new_cmdline .append (to_parse )
666- config_key , separator , header = to_parse .partition ("=" )
667- header_name , colon , _ = header .partition (":" )
685+ for to_parse in cmdline :
686+ if to_parse .startswith ("--config=" ):
687+ option = "--config="
688+ elif to_parse .startswith ("-c" ):
689+ option = "-c"
690+ else :
691+ option = ""
692+ assignment = to_parse [len (option ) :]
693+ # Redact the whole URL first, before splitting on a possible '=' in userinfo.
694+ assignment = _redact_url_credentials (assignment ) or assignment
695+ config_key , separator , value = assignment .partition ("=" )
696+ header_name , colon , _ = value .partition (":" )
668697 if (
669698 separator
670699 and colon
671700 and config_key .lower ().endswith (".extraheader" )
672701 and header_name .strip ().lower () == "authorization"
673702 ):
674- new_cmdline [index ] = "%s%s%s%s *****" % (config_key , separator , header_name , colon )
675- continue
676- try :
677- url = urlsplit (to_parse )
678- # Remove password from the URL if present.
679- if url .password is None and url .username is None :
680- continue
681-
682- # Match urllib.parse's userinfo boundary. Keeping the raw hostinfo
683- # preserves hostname case, IPv6 brackets, and port formatting.
684- _ , _ , hostinfo = url .netloc .rpartition ("@" )
685- redacted = "*****:*****" if url .password is not None else "*****"
686- url = url ._replace (netloc = f"{ redacted } @{ hostinfo } " )
687- new_cmdline [index ] = urlunsplit (url )
688- except ValueError :
689- # This is not a valid URL.
703+ new_cmdline .append ("%s%s%s%s%s *****" % (option , config_key , separator , header_name , colon ))
690704 continue
705+
706+ if separator :
707+ value = _redact_url_credentials (value ) or value
708+ new_cmdline .append (option + config_key + separator + value )
691709 return new_cmdline
692710
693711
0 commit comments