rule.go 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  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})(?:'|"){0,1}`
  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. // secret regexes
  24. hex = `[a-f0-9]`
  25. hex32 = `[a-f0-9]{32}`
  26. hex64 = `[a-f0-9]{64}`
  27. alphaNumeric14 = `[a-z0-9]{14}`
  28. alphaNumeric15 = `[a-z0-9]{15}`
  29. alphaNumeric16 = `[a-z0-9]{16}`
  30. alphaNumeric20 = `[a-z0-9]{20}`
  31. alphaNumeric24 = `[a-z0-9]{24}`
  32. alphaNumeric25 = `[a-z0-9]{25}`
  33. alphaNumeric30 = `[a-z0-9]{30}`
  34. alphaNumeric32 = `[a-z0-9]{32}`
  35. alphaNumeric64 = `[a-z0-9]{64}`
  36. numeric16 = `[0-9]{16}`
  37. numeric18 = `[0-9]{18}`
  38. extendedAlphaNumeric32 = `[a-z0-9=_\-]{32}`
  39. extendedAlphaNumeric60 = `[a-z0-9_\-]{60}`
  40. extendedAlphaNumeric64 = `[a-z0-9_\-]{64}`
  41. // token examples
  42. sampleHex12Token = `b0549eee7368` // gitleaks:allow
  43. sampleHex14Token = `b0549eee7368aa` // gitleaks:allow
  44. sampleHex16Token = `bbb0549eee7368aa` // gitleaks:allow
  45. sampleHex19Token = `d0e94828b0549eee736` // gitleaks:allow
  46. sampleHex20Token = `d0e94828b0549eee7368` // gitleaks:allow
  47. sampleHex24Token = `d0e94828b0549eee73688888` // gitleaks:allow
  48. sampleHex31Token = `d0e94828b0549eee7368e53f6cb41d1` // gitleaks:allow
  49. sampleHex32Token = `d0e94828b0549eee7368e53f6cb41d17` // gitleaks:allow
  50. sampleHex34Token = `d0e94828b0549eee7368e53f6cb41d17aa` // gitleaks:allow
  51. sampleHex35Token = `d0e94828b0549eee7368e53f6cb41d17aaa` // gitleaks:allow
  52. sampleHex40Token = `aaaaad0e94828b0549eee7368e53f6cb41d17aaa` // gitleaks:allow
  53. sampleHex48Token = `aaaaaaaaaaaaad0e94828b0549eee7368e53f6cb41d17aaa` // gitleaks:allow
  54. sampleHex64Token = `d0e94828b0549eee7368e53f6cb41d17d0e94828b0549eee7368e53f6cb41d17` // gitleaks:allow
  55. sampleAlphaNumeric14Token = `00000AAAAAbbbb`
  56. sampleAlphaNumeric15Token = `00000AAAAAbbbbb`
  57. sampleAlphaNumeric16Token = `00000AAAAAbbbbbb`
  58. sampleAlphaNumeric20Token = `00000AAAAAbbbbb99999`
  59. sampleAlphaNumeric22Token = `00000AAAAAbbbbb99999qq`
  60. sampleAlphaNumeric24Token = `00000AAAAAbbbbb99999qqqq`
  61. sampleAlphaNumeric25Token = `00000AAAAAbbbbb99999qqqqq`
  62. sampleAlphaNumeric27Token = `00000AAAAAbbbbb99999qqqqqqq`
  63. sampleAlphaNumeric30Token = `00000AAAAAbbbbb99999aaaaalllll`
  64. sampleAlphaNumeric32Token = `00000AAAAAbbbbb99999aaaaalllllzz`
  65. sampleAlphaNumeric36Token = `00000AAAAAbbbbb9999900000AAAAAbbbbb9`
  66. sampleAlphaNumeric40Token = `000000000AAAAAbbbbb9999900000AAAAAbbbbb9`
  67. sampleAlphaNumeric43Token = `00000AAAAAbbbbb99999aaaaallllpppeqaaaa00000`
  68. sampleAlphaNumeric54Token = `00000AAAAAbbbbb99999aaaaallllpppeqaaaa00000ttttttttttt`
  69. sampleAlphaNumeric64Token = `00000AAAAAbbbbb99999aaaaalllllzz00000AAAAAbbbbb99999aaaaalllllll`
  70. sampleNumeric16 = `1111222233334444`
  71. sampleNumeric18 = `111122223333444422`
  72. sampleExtendedAlphaNumeric64Token = `00000AAAAAbbbbb99999aaaaalllllzz00000AAAAAbbbbb99999aaaaalllll_-`
  73. sampleExtendedAlphaNumeric66Token = `0000000AAAAAbbbbb99999aaaaalllllzz00000AAAAAbbbbb99999aaaaalllll_-`
  74. sampleExtendedAlphaNumeric59Token = `AAAAAbbbbb99999aaaaalllllzz00000AAAAAbbbbb99999aaaaalllll_-`
  75. sampleExtendedAlphaNumeric60Token = `AAAAAAbbbbb99999aaaaalllllzz00000AAAAAbbbbb99999aaaaalllll_-`
  76. sampleExtendedAlphaNumeric40Token = `00AAAAAbbbbb99999aaaaallll_--eq-=aa00000`
  77. sampleExtendedAlphaNumeric43Token = `00000AAAAAbbbbb99999aaaaallll_--eq-=aa00000`
  78. sampleExtendedAlphaNumeric32Token = `00000AAAAAbbbbb99999aaaaalllll=_`
  79. sampleExtendedAlphaNumeric20Token = `bbb99999aaaaalllll=_`
  80. sampleAlphaNumeric60Token = `00000AAAAAbbbbb99999aaaaalllllzz00000AAAAAbbbbb99999aaaaalll`
  81. )
  82. func generateSemiGenericRegex(identifiers []string, secretRegex string) *regexp.Regexp {
  83. var sb strings.Builder
  84. sb.WriteString(caseInsensitive)
  85. sb.WriteString(identifierPrefix)
  86. sb.WriteString(strings.Join(identifiers, "|"))
  87. sb.WriteString(identifierSuffix)
  88. sb.WriteString(operator)
  89. sb.WriteString(secretPrefix)
  90. sb.WriteString(secretRegex)
  91. sb.WriteString(secretSuffix)
  92. return regexp.MustCompile(sb.String())
  93. }
  94. func generateUniqueTokenRegex(secretRegex string) *regexp.Regexp {
  95. var sb strings.Builder
  96. sb.WriteString(caseInsensitive)
  97. sb.WriteString(secretPrefixUnique)
  98. sb.WriteString(secretRegex)
  99. sb.WriteString(secretSuffix)
  100. return regexp.MustCompile(sb.String())
  101. }
  102. func generateSampleSecret(identifier string, secret string) string {
  103. return fmt.Sprintf("%s_api_token = \"%s\"", identifier, secret)
  104. }
  105. func validate(r config.Rule, truePositives []string) *config.Rule {
  106. d := detect.NewDetector(config.Config{
  107. Rules: []*config.Rule{&r},
  108. })
  109. for _, tp := range truePositives {
  110. if len(d.DetectString(tp)) != 1 {
  111. log.Fatal().Msgf("Failed to validate %s", r.RuleID)
  112. }
  113. }
  114. return &r
  115. }