filesatcommit.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. package scan
  2. import (
  3. "path/filepath"
  4. "strings"
  5. "github.com/zricethezav/gitleaks/v7/config"
  6. "github.com/zricethezav/gitleaks/v7/options"
  7. "github.com/go-git/go-git/v5"
  8. "github.com/go-git/go-git/v5/plumbing/object"
  9. )
  10. // FilesAtCommitScanner is a files at commit scanner. This differs from CommitScanner
  11. // as CommitScanner generates patches that are scanned. FilesAtCommitScanner instead looks at
  12. // files available at a commit's worktree and scans the entire content of said files.
  13. // Apologies for the awful struct name...
  14. type FilesAtCommitScanner struct {
  15. opts options.Options
  16. cfg config.Config
  17. repo *git.Repository
  18. commit *object.Commit
  19. repoName string
  20. }
  21. // NewFilesAtCommitScanner creates and returns a files at commit scanner
  22. func NewFilesAtCommitScanner(opts options.Options, cfg config.Config, repo *git.Repository, commit *object.Commit) *FilesAtCommitScanner {
  23. fs := &FilesAtCommitScanner{
  24. opts: opts,
  25. cfg: cfg,
  26. repo: repo,
  27. commit: commit,
  28. repoName: getRepoName(opts),
  29. }
  30. return fs
  31. }
  32. // Scan kicks off a FilesAtCommitScanner Scan
  33. func (fs *FilesAtCommitScanner) Scan() (Report, error) {
  34. var scannerReport Report
  35. if fs.cfg.Allowlist.CommitAllowed(fs.commit.Hash.String()) {
  36. return scannerReport, nil
  37. }
  38. fIter, err := fs.commit.Files()
  39. if err != nil {
  40. return scannerReport, err
  41. }
  42. err = fIter.ForEach(func(f *object.File) error {
  43. bin, err := f.IsBinary()
  44. if bin {
  45. return nil
  46. } else if err != nil {
  47. return err
  48. }
  49. if fs.cfg.Allowlist.FileAllowed(filepath.Base(f.Name)) ||
  50. fs.cfg.Allowlist.PathAllowed(f.Name) {
  51. return nil
  52. }
  53. content, err := f.Contents()
  54. if err != nil {
  55. return err
  56. }
  57. // Check individual file path ONLY rules
  58. for _, rule := range fs.cfg.Rules {
  59. if rule.CommitAllowed(fs.commit.Hash.String()) {
  60. continue
  61. }
  62. if rule.HasFileOrPathLeakOnly(f.Name) {
  63. leak := NewLeak("", "Filename or path offender: "+f.Name, defaultLineNumber).WithCommit(fs.commit)
  64. leak.Repo = fs.repoName
  65. leak.File = f.Name
  66. leak.RepoURL = fs.opts.RepoURL
  67. leak.LeakURL = leak.URL()
  68. leak.Rule = rule.Description
  69. leak.Tags = strings.Join(rule.Tags, ", ")
  70. if fs.opts.Verbose {
  71. leak.Log(fs.opts.Redact)
  72. }
  73. scannerReport.Leaks = append(scannerReport.Leaks, leak)
  74. continue
  75. }
  76. }
  77. for i, line := range strings.Split(content, "\n") {
  78. for _, rule := range fs.cfg.Rules {
  79. if rule.AllowList.FileAllowed(filepath.Base(f.Name)) ||
  80. rule.AllowList.PathAllowed(f.Name) ||
  81. rule.AllowList.CommitAllowed(fs.commit.Hash.String()) {
  82. continue
  83. }
  84. offender := rule.Inspect(line)
  85. if offender == "" {
  86. continue
  87. }
  88. if fs.cfg.Allowlist.RegexAllowed(line) {
  89. continue
  90. }
  91. if rule.File.String() != "" && !rule.HasFileLeak(filepath.Base(f.Name)) {
  92. continue
  93. }
  94. if rule.Path.String() != "" && !rule.HasFilePathLeak(f.Name) {
  95. continue
  96. }
  97. leak := NewLeak(line, offender, defaultLineNumber).WithCommit(fs.commit)
  98. leak.File = f.Name
  99. leak.LineNumber = i + 1
  100. leak.RepoURL = fs.opts.RepoURL
  101. leak.Repo = fs.repoName
  102. leak.LeakURL = leak.URL()
  103. leak.Rule = rule.Description
  104. leak.Tags = strings.Join(rule.Tags, ", ")
  105. if fs.opts.Verbose {
  106. leak.Log(fs.opts.Redact)
  107. }
  108. scannerReport.Leaks = append(scannerReport.Leaks, leak)
  109. }
  110. }
  111. return nil
  112. })
  113. scannerReport.Commits = 1
  114. return scannerReport, err
  115. }