report.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. package scan
  2. import (
  3. "encoding/csv"
  4. "encoding/json"
  5. "os"
  6. "regexp"
  7. "strings"
  8. "time"
  9. "github.com/sirupsen/logrus"
  10. "github.com/zricethezav/gitleaks/v7/config"
  11. "github.com/zricethezav/gitleaks/v7/options"
  12. "github.com/zricethezav/gitleaks/v7/version"
  13. )
  14. // Report is a container for leaks and number of commits scanned
  15. type Report struct {
  16. Leaks []Leak
  17. Commits int
  18. }
  19. // WriteReport accepts a report and options and will write a report if --report has been set
  20. func WriteReport(report Report, opts options.Options, cfg config.Config) error {
  21. if !(opts.NoGit || opts.CheckUncommitted()) {
  22. logrus.Info("commits scanned: ", report.Commits)
  23. }
  24. if len(report.Leaks) != 0 {
  25. logrus.Warn("leaks found: ", len(report.Leaks))
  26. } else {
  27. logrus.Info("No leaks found")
  28. return nil
  29. }
  30. if opts.Report == "" {
  31. return nil
  32. } else {
  33. if opts.Redact {
  34. var redactedLeaks []Leak
  35. for _, leak := range report.Leaks {
  36. redactedLeaks = append(redactedLeaks, RedactLeak(leak))
  37. }
  38. report.Leaks = redactedLeaks
  39. }
  40. file, err := os.Create(opts.Report)
  41. if err != nil {
  42. return err
  43. }
  44. defer rable(file.Close)
  45. switch strings.ToLower(opts.ReportFormat) {
  46. case "json":
  47. encoder := json.NewEncoder(file)
  48. encoder.SetIndent("", " ")
  49. err = encoder.Encode(report.Leaks)
  50. if err != nil {
  51. return err
  52. }
  53. case "csv":
  54. newLineRegex := regexp.MustCompile("[\r]*\n")
  55. w := csv.NewWriter(file)
  56. err = w.Write([]string{"repo", "line", "commit", "offender", "leakURL", "rule", "tags", "commitMsg", "author", "email", "file", "date"})
  57. if err != nil {
  58. return err
  59. }
  60. for _, leak := range report.Leaks {
  61. commitFirstLine := newLineRegex.ReplaceAllString(leak.Message, " ")
  62. err := w.Write([]string{leak.Repo, leak.Line, leak.Commit, leak.Offender, leak.LeakURL, leak.Rule, leak.Tags, commitFirstLine, leak.Author, leak.Email, leak.File, leak.Date.Format(time.RFC3339)})
  63. if err != nil {
  64. return err
  65. }
  66. }
  67. w.Flush()
  68. case "sarif":
  69. s := Sarif{
  70. Schema: "https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0-rtm.5.json",
  71. Version: "2.1.0",
  72. Runs: []Runs{
  73. {
  74. Tool: Tool{
  75. Driver: Driver{
  76. Name: "Gitleaks",
  77. SemanticVersion: version.Version,
  78. Rules: configToRules(cfg),
  79. },
  80. },
  81. Results: leaksToResults(report.Leaks),
  82. },
  83. },
  84. }
  85. encoder := json.NewEncoder(file)
  86. encoder.SetIndent("", " ")
  87. err = encoder.Encode(s)
  88. if err != nil {
  89. return err
  90. }
  91. }
  92. }
  93. return nil
  94. }