redact.go 1.5 KB

1234567891011121314151617181920212223242526272829303132
  1. package stringutil
  2. import (
  3. "regexp"
  4. "strings"
  5. )
  6. // urlPattern matches scheme://... URLs up to the next whitespace or quote.
  7. var urlPattern = regexp.MustCompile(`[a-zA-Z][a-zA-Z0-9+.-]*://[^\s"']+`)
  8. // userInfoPattern matches the user:password@ portion following a URL scheme, up to the last @ before
  9. // the path, so passwords containing @ are fully removed.
  10. var userInfoPattern = regexp.MustCompile(`^([a-zA-Z][a-zA-Z0-9+.-]*://)[^/]*@`)
  11. // secretParamPattern matches the values of well known signature and credential parameters used by
  12. // cloud storage presigned URLs and connection strings, wherever they appear.
  13. var secretParamPattern = regexp.MustCompile(`(?i)\b(sig|signature|x-amz-signature|x-amz-credential|x-amz-security-token|x-goog-signature|x-goog-credential|accountkey|sharedaccesssignature|access_token|token)=[^&;\s"']+`)
  14. // RedactURLs removes query strings, fragments and user info from any URLs contained in s, and the
  15. // values of well known signature and credential parameters anywhere in s, so that error messages
  16. // from storage clients (which may embed presigned URLs or credentials) are safe to expose through
  17. // logs, status endpoints and diagnostics.
  18. func RedactURLs(s string) string {
  19. s = urlPattern.ReplaceAllStringFunc(s, func(u string) string {
  20. u = userInfoPattern.ReplaceAllString(u, "${1}REDACTED@")
  21. if i := strings.IndexAny(u, "?#"); i >= 0 {
  22. return u[:i] + "?REDACTED"
  23. }
  24. return u
  25. })
  26. return secretParamPattern.ReplaceAllString(s, "${1}=REDACTED")
  27. }