@@ -473,10 +473,21 @@ func SameHost(url1, url2 string) bool {
473473// - Various schemes: http, https, ssh, git, ftp, sftp
474474// - IPv6 hosts: https://user@[2001:db8::1]/path
475475func RedactURL (u string ) string {
476- // First, try to parse as a standard URL (handles most schemes)
476+ // Handle SCP-like URLs first: user@host:path (no scheme)
477+ // Must check this BEFORE url.Parse because urls like "oauth2:token@host:path"
478+ // get misinterpreted as having scheme "oauth2".
479+ // This catches: git@github.com:org/repo, deploy@host:repo, oauth2:token@gitlab.com:org/repo
480+ if matches := scpLikeURLRegex .FindStringSubmatch (u ); matches != nil {
481+ // matches[1] = user part (could be git, deploy, oauth2:token, etc.)
482+ // matches[2] = host
483+ // matches[3] = path
484+ return "***@" + matches [2 ] + ":" + matches [3 ]
485+ }
486+
487+ // Try to parse as a standard URL (handles most schemes)
477488 parsed , err := url .Parse (u )
478- if err == nil && parsed .Scheme != "" {
479- // Successfully parsed as a URL with a scheme
489+ if err == nil && parsed .Scheme != "" && parsed . Host != "" {
490+ // Successfully parsed as a URL with a scheme and host
480491 // Redact userinfo if present (handles user, user:pass, token, URL-encoded creds)
481492 if parsed .User != nil {
482493 // Build URL manually to avoid url.User encoding *** as %2A%2A%2A
@@ -492,15 +503,6 @@ func RedactURL(u string) string {
492503 return parsed .String ()
493504 }
494505
495- // Handle SCP-like URLs: user@host:path (no scheme)
496- // This catches: git@github.com:org/repo, deploy@host:repo, user@10.0.0.5:project
497- if matches := scpLikeURLRegex .FindStringSubmatch (u ); matches != nil {
498- // matches[1] = user part (could be git, deploy, token, etc.)
499- // matches[2] = host
500- // matches[3] = path
501- return "***@" + matches [2 ] + ":" + matches [3 ]
502- }
503-
504506 // If we can't parse it and it's not SCP-like, return as-is
505507 // (probably not a URL with credentials)
506508 return u
0 commit comments