redact.go 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839
  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. // any query or fragment, so passwords containing @ or / are fully removed. A path containing @ is
  10. // over-redacted, which fails safe.
  11. var userInfoPattern = regexp.MustCompile(`^([a-zA-Z][a-zA-Z0-9+.-]*://)[^?#]*@`)
  12. // secretParamPattern matches the values of well known signature and credential parameters used by
  13. // cloud storage presigned URLs and connection strings, wherever they appear.
  14. // Values may follow = (query strings, connection strings), : (headers) or ":" (JSON).
  15. 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|refresh_token|client_secret)("?\s*[:=]\s*"?)[^&;,\s"']+`)
  16. // genericSecretPattern matches password and token values only after = or a quoted JSON key, so that
  17. // prose such as "failed to get token: ..." is left intact.
  18. var genericSecretPattern = regexp.MustCompile(`(?i)\b(password|token)(\s*=\s*"?|"\s*:\s*")[^&;,\s"']+`)
  19. // RedactURLs removes query strings, fragments and user info from any URLs contained in s, and the
  20. // values of well known signature and credential parameters anywhere in s, so that error messages
  21. // from storage clients (which may embed presigned URLs or credentials) are safe to expose through
  22. // logs, status endpoints and diagnostics.
  23. func RedactURLs(s string) string {
  24. s = urlPattern.ReplaceAllStringFunc(s, func(u string) string {
  25. u = userInfoPattern.ReplaceAllString(u, "${1}REDACTED@")
  26. if i := strings.IndexAny(u, "?#"); i >= 0 {
  27. return u[:i] + "?REDACTED"
  28. }
  29. return u
  30. })
  31. s = secretParamPattern.ReplaceAllString(s, "${1}${2}REDACTED")
  32. return genericSecretPattern.ReplaceAllString(s, "${1}${2}REDACTED")
  33. }