git.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. package cmd
  2. import (
  3. "time"
  4. "github.com/spf13/cobra"
  5. "github.com/zricethezav/gitleaks/v8/cmd/scm"
  6. "github.com/zricethezav/gitleaks/v8/logging"
  7. "github.com/zricethezav/gitleaks/v8/report"
  8. "github.com/zricethezav/gitleaks/v8/sources"
  9. )
  10. func init() {
  11. rootCmd.AddCommand(gitCmd)
  12. gitCmd.Flags().String("platform", "", "the target platform used to generate links (github, gitlab)")
  13. gitCmd.Flags().Bool("staged", false, "scan staged commits (good for pre-commit)")
  14. gitCmd.Flags().Bool("pre-commit", false, "scan using git diff")
  15. gitCmd.Flags().String("log-opts", "", "git log options")
  16. }
  17. var gitCmd = &cobra.Command{
  18. Use: "git [flags] [repo]",
  19. Short: "scan git repositories for secrets",
  20. Args: cobra.MaximumNArgs(1),
  21. Run: runGit,
  22. }
  23. func runGit(cmd *cobra.Command, args []string) {
  24. // start timer
  25. start := time.Now()
  26. // grab source
  27. source := "."
  28. if len(args) == 1 {
  29. source = args[0]
  30. if source == "" {
  31. source = "."
  32. }
  33. }
  34. // setup config (aka, the thing that defines rules)
  35. initConfig(source)
  36. initDiagnostics()
  37. cfg := Config(cmd)
  38. // create detector
  39. detector := Detector(cmd, cfg, source)
  40. // parse flags
  41. exitCode := mustGetIntFlag(cmd, "exit-code")
  42. logOpts := mustGetStringFlag(cmd, "log-opts")
  43. staged := mustGetBoolFlag(cmd, "staged")
  44. preCommit := mustGetBoolFlag(cmd, "pre-commit")
  45. var (
  46. findings []report.Finding
  47. err error
  48. gitCmd *sources.GitCmd
  49. scmPlatform scm.Platform
  50. )
  51. if preCommit || staged {
  52. if gitCmd, err = sources.NewGitDiffCmdContext(cmd.Context(), source, staged); err != nil {
  53. logging.Fatal().Err(err).Msg("could not create Git diff cmd")
  54. }
  55. // Remote info + links are irrelevant for staged changes.
  56. scmPlatform = scm.NoPlatform
  57. } else {
  58. if gitCmd, err = sources.NewGitLogCmdContext(cmd.Context(), source, logOpts); err != nil {
  59. logging.Fatal().Err(err).Msg("could not create Git log cmd")
  60. }
  61. if scmPlatform, err = scm.PlatformFromString(mustGetStringFlag(cmd, "platform")); err != nil {
  62. logging.Fatal().Err(err).Send()
  63. }
  64. }
  65. findings, err = detector.DetectSource(
  66. cmd.Context(),
  67. &sources.Git{
  68. Cmd: gitCmd,
  69. Config: &detector.Config,
  70. Remote: sources.NewRemoteInfoContext(cmd.Context(), scmPlatform, source),
  71. Sema: detector.Sema,
  72. MaxArchiveDepth: detector.MaxArchiveDepth,
  73. },
  74. )
  75. if err != nil {
  76. // don't exit on error, just log it
  77. logging.Error().Err(err).Msg("failed to scan Git repository")
  78. }
  79. findingSummaryAndExit(detector, findings, exitCode, start, err)
  80. }