checks.go 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. package main
  2. import (
  3. "math"
  4. "strings"
  5. )
  6. // checks Regex and if enabled, entropy and stopwords
  7. func doChecks(diff string, commit string) []LeakElem {
  8. var match string
  9. var leaks []LeakElem
  10. var leak LeakElem
  11. lines := strings.Split(diff, "\n")
  12. for _, line := range lines {
  13. for leakType, re := range regexes {
  14. match = re.FindString(line)
  15. if len(match) == 0 ||
  16. (opts.Strict && containsStopWords(line)) ||
  17. (opts.Entropy && !checkShannonEntropy(line)) {
  18. continue
  19. }
  20. leak = LeakElem{
  21. Line: line,
  22. Commit: commit,
  23. Offender: match,
  24. Reason: leakType,
  25. }
  26. leaks = append(leaks, leak)
  27. }
  28. }
  29. return leaks
  30. }
  31. // checkShannonEntropy checks entropy of target
  32. func checkShannonEntropy(target string) bool {
  33. var (
  34. sum float64
  35. targetBase64Len int
  36. targetHexLen int
  37. base64Freq = make(map[rune]float64)
  38. hexFreq = make(map[rune]float64)
  39. bits int
  40. )
  41. index := assignRegex.FindStringIndex(target)
  42. if len(index) == 0 {
  43. return false
  44. }
  45. target = strings.Trim(target[index[1]:], " ")
  46. if len(target) > 100 {
  47. return false
  48. }
  49. // base64Shannon
  50. for _, i := range target {
  51. if strings.Contains(base64Chars, string(i)) {
  52. base64Freq[i]++
  53. targetBase64Len++
  54. }
  55. }
  56. for _, v := range base64Freq {
  57. f := v / float64(targetBase64Len)
  58. sum += f * math.Log2(f)
  59. }
  60. bits = int(math.Ceil(sum*-1)) * targetBase64Len
  61. if bits > opts.B64EntropyCutoff {
  62. return true
  63. }
  64. // hexShannon
  65. sum = 0
  66. for _, i := range target {
  67. if strings.Contains(hexChars, string(i)) {
  68. hexFreq[i]++
  69. targetHexLen++
  70. }
  71. }
  72. for _, v := range hexFreq {
  73. f := v / float64(targetHexLen)
  74. sum += f * math.Log2(f)
  75. }
  76. bits = int(math.Ceil(sum*-1)) * targetHexLen
  77. return bits > opts.HexEntropyCutoff
  78. }
  79. // containsStopWords checks if there are any stop words in target
  80. func containsStopWords(target string) bool {
  81. for _, stopWord := range stopWords {
  82. if strings.Contains(target, stopWord) {
  83. return true
  84. }
  85. }
  86. return false
  87. }