allowlist.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. package config
  2. import (
  3. "fmt"
  4. "strings"
  5. "golang.org/x/exp/maps"
  6. "github.com/zricethezav/gitleaks/v8/regexp"
  7. )
  8. type AllowlistMatchCondition int
  9. const (
  10. AllowlistMatchOr AllowlistMatchCondition = iota
  11. AllowlistMatchAnd
  12. )
  13. func (a AllowlistMatchCondition) String() string {
  14. return [...]string{
  15. "OR",
  16. "AND",
  17. }[a]
  18. }
  19. // Allowlist allows a rule to be ignored for specific
  20. // regexes, paths, and/or commits
  21. type Allowlist struct {
  22. // Short human readable description of the allowlist.
  23. Description string
  24. // MatchCondition determines whether all criteria must match.
  25. MatchCondition AllowlistMatchCondition
  26. // Commits is a slice of commit SHAs that are allowed to be ignored. Defaults to "OR".
  27. Commits []string
  28. // Paths is a slice of path regular expressions that are allowed to be ignored.
  29. Paths []*regexp.Regexp
  30. // Can be `match` or `line`.
  31. //
  32. // If `match` the _Regexes_ will be tested against the match of the _Rule.Regex_.
  33. //
  34. // If `line` the _Regexes_ will be tested against the entire line.
  35. //
  36. // If RegexTarget is empty, it will be tested against the found secret.
  37. RegexTarget string
  38. // Regexes is slice of content regular expressions that are allowed to be ignored.
  39. Regexes []*regexp.Regexp
  40. // StopWords is a slice of stop words that are allowed to be ignored.
  41. // This targets the _secret_, not the content of the regex match like the
  42. // Regexes slice.
  43. StopWords []string
  44. // validated is an internal flag to track whether `Validate()` has been called.
  45. validated bool
  46. }
  47. // CommitAllowed returns true if the commit is allowed to be ignored.
  48. func (a *Allowlist) CommitAllowed(c string) (bool, string) {
  49. if a == nil || c == "" {
  50. return false, ""
  51. }
  52. for _, commit := range a.Commits {
  53. if commit == c {
  54. return true, c
  55. }
  56. }
  57. return false, ""
  58. }
  59. // PathAllowed returns true if the path is allowed to be ignored.
  60. func (a *Allowlist) PathAllowed(path string) bool {
  61. if a == nil || path == "" {
  62. return false
  63. }
  64. return anyRegexMatch(path, a.Paths)
  65. }
  66. // RegexAllowed returns true if the regex is allowed to be ignored.
  67. func (a *Allowlist) RegexAllowed(secret string) bool {
  68. if a == nil || secret == "" {
  69. return false
  70. }
  71. return anyRegexMatch(secret, a.Regexes)
  72. }
  73. func (a *Allowlist) ContainsStopWord(s string) (bool, string) {
  74. if a == nil || s == "" {
  75. return false, ""
  76. }
  77. s = strings.ToLower(s)
  78. for _, stopWord := range a.StopWords {
  79. if strings.Contains(s, strings.ToLower(stopWord)) {
  80. return true, stopWord
  81. }
  82. }
  83. return false, ""
  84. }
  85. func (a *Allowlist) Validate() error {
  86. if a.validated {
  87. return nil
  88. }
  89. // Disallow empty allowlists.
  90. if len(a.Commits) == 0 &&
  91. len(a.Paths) == 0 &&
  92. len(a.Regexes) == 0 &&
  93. len(a.StopWords) == 0 {
  94. return fmt.Errorf("[[rules.allowlists]] must contain at least one check for: commits, paths, regexes, or stopwords")
  95. }
  96. // Deduplicate commits and stopwords.
  97. if len(a.Commits) > 0 {
  98. uniqueCommits := make(map[string]struct{})
  99. for _, commit := range a.Commits {
  100. uniqueCommits[commit] = struct{}{}
  101. }
  102. a.Commits = maps.Keys(uniqueCommits)
  103. }
  104. if len(a.StopWords) > 0 {
  105. uniqueStopwords := make(map[string]struct{})
  106. for _, stopWord := range a.StopWords {
  107. uniqueStopwords[stopWord] = struct{}{}
  108. }
  109. a.StopWords = maps.Keys(uniqueStopwords)
  110. }
  111. a.validated = true
  112. return nil
  113. }