rule.go 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. package rules
  2. import (
  3. "fmt"
  4. "regexp"
  5. "strings"
  6. "github.com/rs/zerolog/log"
  7. "github.com/zricethezav/gitleaks/v8/config"
  8. "github.com/zricethezav/gitleaks/v8/detect"
  9. )
  10. const (
  11. // case insensitive prefix
  12. caseInsensitive = `(?i)`
  13. // identifier prefix (just an ignore group)
  14. identifierPrefix = `(?:`
  15. identifierSuffix = `)(?:[0-9a-z\-_\s.]{0,20})(?:[\s|']|[\s|"]){0,3}`
  16. // commonly used assignment operators or function call
  17. operator = `(?:=|>|:=|\|\|:|<=|=>|:)`
  18. // boundaries for the secret
  19. // \x60 = `
  20. secretPrefixUnique = `\b(`
  21. secretPrefix = `(?:'|\"|\s|=|\x60){0,5}(`
  22. secretSuffix = `)(?:['|\"|\n|\r|\s|\x60]|$)`
  23. )
  24. func generateSemiGenericRegex(identifiers []string, secretRegex string) *regexp.Regexp {
  25. var sb strings.Builder
  26. sb.WriteString(caseInsensitive)
  27. sb.WriteString(identifierPrefix)
  28. sb.WriteString(strings.Join(identifiers, "|"))
  29. sb.WriteString(identifierSuffix)
  30. sb.WriteString(operator)
  31. sb.WriteString(secretPrefix)
  32. sb.WriteString(secretRegex)
  33. sb.WriteString(secretSuffix)
  34. return regexp.MustCompile(sb.String())
  35. }
  36. func generateUniqueTokenRegex(secretRegex string) *regexp.Regexp {
  37. var sb strings.Builder
  38. sb.WriteString(caseInsensitive)
  39. sb.WriteString(secretPrefixUnique)
  40. sb.WriteString(secretRegex)
  41. sb.WriteString(secretSuffix)
  42. return regexp.MustCompile(sb.String())
  43. }
  44. func generateSampleSecret(identifier string, secret string) string {
  45. return fmt.Sprintf("%s_api_token = \"%s\"", identifier, secret)
  46. }
  47. func validate(r config.Rule, truePositives []string) *config.Rule {
  48. // normalize keywords like in the config package
  49. var keywords []string
  50. for _, k := range r.Keywords {
  51. keywords = append(keywords, strings.ToLower(k))
  52. }
  53. r.Keywords = keywords
  54. d := detect.NewDetector(config.Config{
  55. Rules: []*config.Rule{&r},
  56. Keywords: keywords,
  57. })
  58. for _, tp := range truePositives {
  59. if len(d.DetectString(tp)) != 1 {
  60. log.Fatal().Msgf("Failed to validate %s", r.RuleID)
  61. }
  62. }
  63. return &r
  64. }
  65. func numeric(size string) string {
  66. return fmt.Sprintf(`[0-9]{%s}`, size)
  67. }
  68. func hex(size string) string {
  69. return fmt.Sprintf(`[a-f0-9]{%s}`, size)
  70. }
  71. func alphaNumeric(size string) string {
  72. return fmt.Sprintf(`[a-z0-9]{%s}`, size)
  73. }
  74. func alphaNumericExtended(size string) string {
  75. return fmt.Sprintf(`[a-z0-9=_\-]{%s}`, size)
  76. }