add testing files and create create scan command

pull/580/head infisical-cli/v0.5.0
Maidul Islam 1 year ago
parent b3e68cf3fb
commit 8249043826

@ -3,8 +3,15 @@ Copyright (c) 2023 Infisical Inc.
*/
package main
import "github.com/Infisical/infisical-merge/packages/cmd"
import (
"os"
"github.com/Infisical/infisical-merge/packages/cmd"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
)
func main() {
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
cmd.Execute()
}

@ -19,7 +19,7 @@ import (
// runCmd represents the run command
var initCmd = &cobra.Command{
Use: "init",
Short: "Used to initialize your project with Infisical",
Short: "Used to connect your local project with Infisical project",
DisableFlagsInUseLine: true,
Example: "infisical init",
Args: cobra.ExactArgs(0),

@ -12,7 +12,7 @@ import (
var resetCmd = &cobra.Command{
Use: "reset",
Short: "Used delete all Infisical related data on your machine",
Short: "Used to delete all Infisical related data on your machine",
DisableFlagsInUseLine: true,
Example: "infisical reset",
Args: cobra.NoArgs,

@ -52,8 +52,6 @@ func init() {
}
func initLog() {
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
zerolog.SetGlobalLevel(zerolog.InfoLevel)
ll, err := rootCmd.Flags().GetString("log-level")
if err != nil {

@ -1,307 +0,0 @@
// MIT License
// Copyright (c) 2019 Zachary Rice
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
package cmd
import (
"os"
"path/filepath"
"strings"
"time"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/Infisical/infisical-merge/config"
"github.com/Infisical/infisical-merge/detect"
"github.com/Infisical/infisical-merge/report"
)
func init() {
rootCmd.AddCommand(detectCmd)
detectCmd.Flags().String("log-opts", "", "git log options")
detectCmd.Flags().Bool("no-git", false, "treat git repo as a regular directory and scan those files, --log-opts has no effect on the scan when --no-git is set")
detectCmd.Flags().Bool("pipe", false, "scan input from stdin, ex: `cat some_file | gitleaks detect --pipe`")
detectCmd.Flags().Bool("follow-symlinks", false, "scan files that are symlinks to other files")
detectCmd.Flags().StringP("config", "c", "", configDescription)
detectCmd.Flags().Int("exit-code", 1, "exit code when leaks have been encountered")
detectCmd.Flags().StringP("source", "s", ".", "path to source")
detectCmd.Flags().StringP("report-path", "r", "", "report file")
detectCmd.Flags().StringP("report-format", "f", "json", "output format (json, csv, sarif)")
detectCmd.Flags().StringP("baseline-path", "b", "", "path to baseline with issues that can be ignored")
detectCmd.Flags().BoolP("verbose", "v", false, "show verbose output from scan (which file, where in the file, what secret)")
detectCmd.Flags().BoolP("no-color", "", false, "turn off color for verbose output")
detectCmd.Flags().Int("max-target-megabytes", 0, "files larger than this will be skipped")
detectCmd.Flags().Bool("redact", false, "redact secrets from logs and stdout")
err := viper.BindPFlag("config", detectCmd.Flags().Lookup("config"))
if err != nil {
log.Fatal().Msgf("err binding config %s", err.Error())
}
// Hide the flag
detectCmd.Flags().MarkHidden("config")
}
var detectCmd = &cobra.Command{
Use: "scan",
Short: "scan for secrets in repos, directories, and files",
Run: runDetect,
}
func runDetect(cmd *cobra.Command, args []string) {
initScanConfig(cmd)
var (
vc config.ViperConfig
findings []report.Finding
err error
)
// Load config
if err = viper.Unmarshal(&vc); err != nil {
log.Fatal().Err(err).Msg("Failed to load config")
}
cfg, err := vc.Translate()
if err != nil {
log.Fatal().Err(err).Msg("Failed to load config")
}
cfg.Path, _ = cmd.Flags().GetString("config")
// start timer
start := time.Now()
// Setup detector
detector := detect.NewDetector(cfg)
detector.Config.Path, err = cmd.Flags().GetString("config")
if err != nil {
log.Fatal().Err(err).Msg("")
}
source, err := cmd.Flags().GetString("source")
if err != nil {
log.Fatal().Err(err).Msg("")
}
// if config path is not set, then use the {source}/.gitleaks.toml path.
// note that there may not be a `{source}/.gitleaks.toml` file, this is ok.
if detector.Config.Path == "" {
detector.Config.Path = filepath.Join(source, ".gitleaks.toml")
}
// set verbose flag
if detector.Verbose, err = cmd.Flags().GetBool("verbose"); err != nil {
log.Fatal().Err(err).Msg("")
}
// set redact flag
if detector.Redact, err = cmd.Flags().GetBool("redact"); err != nil {
log.Fatal().Err(err).Msg("")
}
if detector.MaxTargetMegaBytes, err = cmd.Flags().GetInt("max-target-megabytes"); err != nil {
log.Fatal().Err(err).Msg("")
}
// set color flag
if detector.NoColor, err = cmd.Flags().GetBool("no-color"); err != nil {
log.Fatal().Err(err).Msg("")
}
if fileExists(filepath.Join(source, ".infisicalignore")) {
if err = detector.AddGitleaksIgnore(filepath.Join(source, ".infisicalignore")); err != nil {
log.Fatal().Err(err).Msg("could not call AddInfisicalIgnore")
}
}
// ignore findings from the baseline (an existing report in json format generated earlier)
baselinePath, _ := cmd.Flags().GetString("baseline-path")
if baselinePath != "" {
err = detector.AddBaseline(baselinePath, source)
if err != nil {
log.Error().Msgf("Could not load baseline. The path must point of a gitleaks report generated using the default format: %s", err)
}
}
// set follow symlinks flag
if detector.FollowSymlinks, err = cmd.Flags().GetBool("follow-symlinks"); err != nil {
log.Fatal().Err(err).Msg("")
}
// set exit code
exitCode, err := cmd.Flags().GetInt("exit-code")
if err != nil {
log.Fatal().Err(err).Msg("could not get exit code")
}
// determine what type of scan:
// - git: scan the history of the repo
// - no-git: scan files by treating the repo as a plain directory
noGit, err := cmd.Flags().GetBool("no-git")
if err != nil {
log.Fatal().Err(err).Msg("could not call GetBool() for no-git")
}
fromPipe, err := cmd.Flags().GetBool("pipe")
if err != nil {
log.Fatal().Err(err)
}
// start the detector scan
if noGit {
findings, err = detector.DetectFiles(source)
if err != nil {
// don't exit on error, just log it
log.Error().Err(err).Msg("")
}
} else if fromPipe {
findings, err = detector.DetectReader(os.Stdin, 10)
if err != nil {
// log fatal to exit, no need to continue since a report
// will not be generated when scanning from a pipe...for now
log.Fatal().Err(err).Msg("")
}
} else {
var logOpts string
logOpts, err = cmd.Flags().GetString("log-opts")
if err != nil {
log.Fatal().Err(err).Msg("")
}
findings, err = detector.DetectGit(source, logOpts, detect.DetectType)
if err != nil {
// don't exit on error, just log it
log.Error().Err(err).Msg("")
}
}
// log info about the scan
if err == nil {
log.Info().Msgf("scan completed in %s", FormatDuration(time.Since(start)))
if len(findings) != 0 {
log.Warn().Msgf("leaks found: %d", len(findings))
} else {
log.Info().Msg("no leaks found")
}
} else {
log.Warn().Msgf("partial scan completed in %s", FormatDuration(time.Since(start)))
if len(findings) != 0 {
log.Warn().Msgf("%d leaks found in partial scan", len(findings))
} else {
log.Warn().Msg("no leaks found in partial scan")
}
}
// write report if desired
reportPath, _ := cmd.Flags().GetString("report-path")
ext, _ := cmd.Flags().GetString("report-format")
if reportPath != "" {
if err := report.Write(findings, cfg, ext, reportPath); err != nil {
log.Fatal().Err(err).Msg("could not write")
}
}
if err != nil {
os.Exit(1)
}
if len(findings) != 0 {
os.Exit(exitCode)
}
}
func fileExists(fileName string) bool {
// check for a .gitleaksignore file
info, err := os.Stat(fileName)
if err != nil && !os.IsNotExist(err) {
return false
}
if info != nil && err == nil {
if !info.IsDir() {
return true
}
}
return false
}
func FormatDuration(d time.Duration) string {
scale := 100 * time.Second
// look for the max scale that is smaller than d
for scale > d {
scale = scale / 10
}
return d.Round(scale / 100).String()
}
const configDescription = `config file path
order of precedence:
1. --config/-c
2. env var GITLEAKS_CONFIG
3. (--source/-s)/.gitleaks.toml
If none of the three options are used, then gitleaks will use the default config`
func initScanConfig(cmd *cobra.Command) {
cfgPath, err := cmd.Flags().GetString("config")
if err != nil {
log.Fatal().Msg(err.Error())
}
if cfgPath != "" {
viper.SetConfigFile(cfgPath)
log.Debug().Msgf("using gitleaks config %s from `--config`", cfgPath)
} else if os.Getenv("GITLEAKS_CONFIG") != "" {
envPath := os.Getenv("GITLEAKS_CONFIG")
viper.SetConfigFile(envPath)
log.Debug().Msgf("using gitleaks config from GITLEAKS_CONFIG env var: %s", envPath)
} else {
source, err := cmd.Flags().GetString("source")
if err != nil {
log.Fatal().Msg(err.Error())
}
fileInfo, err := os.Stat(source)
if err != nil {
log.Fatal().Msg(err.Error())
}
if !fileInfo.IsDir() {
log.Debug().Msgf("unable to load gitleaks config from %s since --source=%s is a file, using default config",
filepath.Join(source, ".gitleaks.toml"), source)
viper.SetConfigType("toml")
if err = viper.ReadConfig(strings.NewReader(config.DefaultConfig)); err != nil {
log.Fatal().Msgf("err reading toml %s", err.Error())
}
return
}
if _, err := os.Stat(filepath.Join(source, ".gitleaks.toml")); os.IsNotExist(err) {
log.Debug().Msgf("no gitleaks config found in path %s, using default gitleaks config", filepath.Join(source, ".gitleaks.toml"))
viper.SetConfigType("toml")
if err = viper.ReadConfig(strings.NewReader(config.DefaultConfig)); err != nil {
log.Fatal().Msgf("err reading default config toml %s", err.Error())
}
return
} else {
log.Debug().Msgf("using existing gitleaks config %s from `(--source)/.gitleaks.toml`", filepath.Join(source, ".gitleaks.toml"))
}
viper.AddConfigPath(source)
viper.SetConfigName(".gitleaks")
viper.SetConfigType("toml")
}
if err := viper.ReadInConfig(); err != nil {
log.Fatal().Msgf("unable to load gitleaks config, err: %s", err)
}
}

@ -1,160 +0,0 @@
// MIT License
// Copyright (c) 2019 Zachary Rice
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
package cmd
import (
"os"
"path/filepath"
"time"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/Infisical/infisical-merge/config"
"github.com/Infisical/infisical-merge/detect"
"github.com/Infisical/infisical-merge/report"
)
func init() {
protectCmd.Flags().Bool("staged", false, "detect secrets in a --staged state")
protectCmd.Flags().String("log-opts", "", "git log options")
protectCmd.Flags().StringP("config", "c", "", configDescription)
protectCmd.Flags().Int("exit-code", 1, "exit code when leaks have been encountered")
protectCmd.Flags().StringP("source", "s", ".", "path to source")
protectCmd.Flags().StringP("report-path", "r", "", "report file")
protectCmd.Flags().StringP("report-format", "f", "json", "output format (json, csv, sarif)")
protectCmd.Flags().StringP("baseline-path", "b", "", "path to baseline with issues that can be ignored")
protectCmd.Flags().BoolP("verbose", "v", false, "show verbose output from scan (which file, where in the file, what secret)")
protectCmd.Flags().BoolP("no-color", "", false, "turn off color for verbose output")
protectCmd.Flags().Int("max-target-megabytes", 0, "files larger than this will be skipped")
protectCmd.Flags().Bool("redact", false, "redact secrets from logs and stdout")
err := viper.BindPFlag("config", protectCmd.Flags().Lookup("config"))
if err != nil {
log.Fatal().Msgf("err binding config %s", err.Error())
}
// Hide the flag
protectCmd.Flags().MarkHidden("config")
rootCmd.AddCommand(protectCmd)
}
var protectCmd = &cobra.Command{
Use: "prevent",
Short: "scan for secrets in uncommitted changes in a git repo",
Run: runProtect,
}
func runProtect(cmd *cobra.Command, args []string) {
initScanConfig(cmd)
var vc config.ViperConfig
if err := viper.Unmarshal(&vc); err != nil {
log.Fatal().Err(err).Msg("Failed to load config")
}
cfg, err := vc.Translate()
if err != nil {
log.Fatal().Err(err).Msg("Failed to load config")
}
cfg.Path, _ = cmd.Flags().GetString("config")
exitCode, _ := cmd.Flags().GetInt("exit-code")
staged, _ := cmd.Flags().GetBool("staged")
start := time.Now()
// Setup detector
detector := detect.NewDetector(cfg)
detector.Config.Path, err = cmd.Flags().GetString("config")
if err != nil {
log.Fatal().Err(err).Msg("")
}
source, err := cmd.Flags().GetString("source")
if err != nil {
log.Fatal().Err(err).Msg("")
}
// if config path is not set, then use the {source}/.gitleaks.toml path.
// note that there may not be a `{source}/.gitleaks.toml` file, this is ok.
if detector.Config.Path == "" {
detector.Config.Path = filepath.Join(source, ".gitleaks.toml")
}
// set verbose flag
if detector.Verbose, err = cmd.Flags().GetBool("verbose"); err != nil {
log.Fatal().Err(err).Msg("")
}
// set redact flag
if detector.Redact, err = cmd.Flags().GetBool("redact"); err != nil {
log.Fatal().Err(err).Msg("")
}
if detector.MaxTargetMegaBytes, err = cmd.Flags().GetInt("max-target-megabytes"); err != nil {
log.Fatal().Err(err).Msg("")
}
// set color flag
if detector.NoColor, err = cmd.Flags().GetBool("no-color"); err != nil {
log.Fatal().Err(err).Msg("")
}
if fileExists(filepath.Join(source, ".infisicalignore")) {
if err = detector.AddGitleaksIgnore(filepath.Join(source, ".infisicalignore")); err != nil {
log.Fatal().Err(err).Msg("could not call AddInfisicalIgnore")
}
}
// get log options for git scan
logOpts, err := cmd.Flags().GetString("log-opts")
if err != nil {
log.Fatal().Err(err).Msg("")
}
// start git scan
var findings []report.Finding
if staged {
findings, err = detector.DetectGit(source, logOpts, detect.ProtectStagedType)
} else {
findings, err = detector.DetectGit(source, logOpts, detect.ProtectType)
}
if err != nil {
// don't exit on error, just log it
log.Error().Err(err).Msg("")
}
// log info about the scan
log.Info().Msgf("scan completed in %s", FormatDuration(time.Since(start)))
if len(findings) != 0 {
log.Warn().Msgf("leaks found: %d", len(findings))
} else {
log.Info().Msg("no leaks found")
}
reportPath, _ := cmd.Flags().GetString("report-path")
ext, _ := cmd.Flags().GetString("report-format")
if reportPath != "" {
if err = report.Write(findings, cfg, ext, reportPath); err != nil {
log.Fatal().Err(err).Msg("")
}
}
if len(findings) != 0 {
os.Exit(exitCode)
}
}

@ -0,0 +1,411 @@
// MIT License
// Copyright (c) 2019 Zachary Rice
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
package cmd
import (
"os"
"path/filepath"
"strings"
"time"
"github.com/Infisical/infisical-merge/config"
"github.com/Infisical/infisical-merge/detect"
"github.com/Infisical/infisical-merge/report"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
const configDescription = `config file path
order of precedence:
1. --config/-c
2. env var GITLEAKS_CONFIG
3. (--source/-s)/.gitleaks.toml
If none of the three options are used, then gitleaks will use the default config`
func init() {
// scan flag for only scan command
scanCmd.Flags().String("log-opts", "", "git log options")
scanCmd.Flags().Bool("no-git", false, "treat git repo as a regular directory and scan those files, --log-opts has no effect on the scan when --no-git is set")
scanCmd.Flags().Bool("pipe", false, "scan input from stdin, ex: `cat some_file | gitleaks detect --pipe`")
scanCmd.Flags().Bool("follow-symlinks", false, "scan files that are symlinks to other files")
// global scan flags
scanCmd.PersistentFlags().StringP("config", "c", "", configDescription)
scanCmd.PersistentFlags().Int("exit-code", 1, "exit code when leaks have been encountered")
scanCmd.PersistentFlags().StringP("source", "s", ".", "path to source")
scanCmd.PersistentFlags().StringP("report-path", "r", "", "report file")
scanCmd.PersistentFlags().StringP("report-format", "f", "json", "output format (json, csv, sarif)")
scanCmd.PersistentFlags().StringP("baseline-path", "b", "", "path to baseline with issues that can be ignored")
scanCmd.PersistentFlags().BoolP("verbose", "v", false, "show verbose output from scan (which file, where in the file, what secret)")
scanCmd.PersistentFlags().BoolP("no-color", "", false, "turn off color for verbose output")
scanCmd.PersistentFlags().Int("max-target-megabytes", 0, "files larger than this will be skipped")
scanCmd.PersistentFlags().Bool("redact", false, "redact secrets from logs and stdout")
// scan git changes command flags
scanGitChangesCmd.Flags().Bool("staged", false, "detect secrets in a --staged state")
scanGitChangesCmd.Flags().String("log-opts", "", "git log options")
// find config source
err := viper.BindPFlag("config", scanCmd.PersistentFlags().Lookup("config"))
if err != nil {
log.Fatal().Msgf("err binding config %s", err.Error())
}
// add flags to main
scanCmd.AddCommand(scanGitChangesCmd)
rootCmd.AddCommand(scanCmd)
// Hide flags
scanCmd.PersistentFlags().MarkHidden("config")
}
func initScanConfig(cmd *cobra.Command) {
cfgPath, err := cmd.Flags().GetString("config")
if err != nil {
log.Fatal().Msg(err.Error())
}
if cfgPath != "" {
viper.SetConfigFile(cfgPath)
log.Debug().Msgf("using gitleaks config %s from `--config`", cfgPath)
} else if os.Getenv("GITLEAKS_CONFIG") != "" {
envPath := os.Getenv("GITLEAKS_CONFIG")
viper.SetConfigFile(envPath)
log.Debug().Msgf("using gitleaks config from GITLEAKS_CONFIG env var: %s", envPath)
} else {
source, err := cmd.Flags().GetString("source")
if err != nil {
log.Fatal().Msg(err.Error())
}
fileInfo, err := os.Stat(source)
if err != nil {
log.Fatal().Msg(err.Error())
}
if !fileInfo.IsDir() {
log.Debug().Msgf("unable to load gitleaks config from %s since --source=%s is a file, using default config",
filepath.Join(source, ".gitleaks.toml"), source)
viper.SetConfigType("toml")
if err = viper.ReadConfig(strings.NewReader(config.DefaultConfig)); err != nil {
log.Fatal().Msgf("err reading toml %s", err.Error())
}
return
}
if _, err := os.Stat(filepath.Join(source, ".gitleaks.toml")); os.IsNotExist(err) {
log.Debug().Msgf("no gitleaks config found in path %s, using default gitleaks config", filepath.Join(source, ".gitleaks.toml"))
viper.SetConfigType("toml")
if err = viper.ReadConfig(strings.NewReader(config.DefaultConfig)); err != nil {
log.Fatal().Msgf("err reading default config toml %s", err.Error())
}
return
} else {
log.Debug().Msgf("using existing gitleaks config %s from `(--source)/.gitleaks.toml`", filepath.Join(source, ".gitleaks.toml"))
}
viper.AddConfigPath(source)
viper.SetConfigName(".gitleaks")
viper.SetConfigType("toml")
}
if err := viper.ReadInConfig(); err != nil {
log.Fatal().Msgf("unable to load gitleaks config, err: %s", err)
}
}
var scanCmd = &cobra.Command{
Use: "scan",
Short: "Scan for leaked secrets in git history, directories, and files",
Run: func(cmd *cobra.Command, args []string) {
initScanConfig(cmd)
var (
vc config.ViperConfig
findings []report.Finding
err error
)
// Load config
if err = viper.Unmarshal(&vc); err != nil {
log.Fatal().Err(err).Msg("Failed to load config")
}
cfg, err := vc.Translate()
if err != nil {
log.Fatal().Err(err).Msg("Failed to load config")
}
cfg.Path, _ = cmd.Flags().GetString("config")
// start timer
start := time.Now()
// Setup detector
detector := detect.NewDetector(cfg)
detector.Config.Path, err = cmd.Flags().GetString("config")
if err != nil {
log.Fatal().Err(err).Msg("")
}
source, err := cmd.Flags().GetString("source")
if err != nil {
log.Fatal().Err(err).Msg("")
}
// if config path is not set, then use the {source}/.gitleaks.toml path.
// note that there may not be a `{source}/.gitleaks.toml` file, this is ok.
if detector.Config.Path == "" {
detector.Config.Path = filepath.Join(source, ".gitleaks.toml")
}
// set verbose flag
if detector.Verbose, err = cmd.Flags().GetBool("verbose"); err != nil {
log.Fatal().Err(err).Msg("")
}
// set redact flag
if detector.Redact, err = cmd.Flags().GetBool("redact"); err != nil {
log.Fatal().Err(err).Msg("")
}
if detector.MaxTargetMegaBytes, err = cmd.Flags().GetInt("max-target-megabytes"); err != nil {
log.Fatal().Err(err).Msg("")
}
// set color flag
if detector.NoColor, err = cmd.Flags().GetBool("no-color"); err != nil {
log.Fatal().Err(err).Msg("")
}
if fileExists(filepath.Join(source, ".infisicalignore")) {
if err = detector.AddGitleaksIgnore(filepath.Join(source, ".infisicalignore")); err != nil {
log.Fatal().Err(err).Msg("could not call AddInfisicalIgnore")
}
}
// ignore findings from the baseline (an existing report in json format generated earlier)
baselinePath, _ := cmd.Flags().GetString("baseline-path")
if baselinePath != "" {
err = detector.AddBaseline(baselinePath, source)
if err != nil {
log.Error().Msgf("Could not load baseline. The path must point of a gitleaks report generated using the default format: %s", err)
}
}
// set follow symlinks flag
if detector.FollowSymlinks, err = cmd.Flags().GetBool("follow-symlinks"); err != nil {
log.Fatal().Err(err).Msg("")
}
// set exit code
exitCode, err := cmd.Flags().GetInt("exit-code")
if err != nil {
log.Fatal().Err(err).Msg("could not get exit code")
}
// determine what type of scan:
// - git: scan the history of the repo
// - no-git: scan files by treating the repo as a plain directory
noGit, err := cmd.Flags().GetBool("no-git")
if err != nil {
log.Fatal().Err(err).Msg("could not call GetBool() for no-git")
}
fromPipe, err := cmd.Flags().GetBool("pipe")
if err != nil {
log.Fatal().Err(err)
}
// start the detector scan
if noGit {
findings, err = detector.DetectFiles(source)
if err != nil {
// don't exit on error, just log it
log.Error().Err(err).Msg("")
}
} else if fromPipe {
findings, err = detector.DetectReader(os.Stdin, 10)
if err != nil {
// log fatal to exit, no need to continue since a report
// will not be generated when scanning from a pipe...for now
log.Fatal().Err(err).Msg("")
}
} else {
var logOpts string
logOpts, err = cmd.Flags().GetString("log-opts")
if err != nil {
log.Fatal().Err(err).Msg("")
}
findings, err = detector.DetectGit(source, logOpts, detect.DetectType)
if err != nil {
// don't exit on error, just log it
log.Error().Err(err).Msg("")
}
}
// log info about the scan
if err == nil {
log.Info().Msgf("scan completed in %s", FormatDuration(time.Since(start)))
if len(findings) != 0 {
log.Warn().Msgf("leaks found: %d", len(findings))
} else {
log.Info().Msg("no leaks found")
}
} else {
log.Warn().Msgf("partial scan completed in %s", FormatDuration(time.Since(start)))
if len(findings) != 0 {
log.Warn().Msgf("%d leaks found in partial scan", len(findings))
} else {
log.Warn().Msg("no leaks found in partial scan")
}
}
// write report if desired
reportPath, _ := cmd.Flags().GetString("report-path")
ext, _ := cmd.Flags().GetString("report-format")
if reportPath != "" {
if err := report.Write(findings, cfg, ext, reportPath); err != nil {
log.Fatal().Err(err).Msg("could not write")
}
}
if err != nil {
os.Exit(1)
}
if len(findings) != 0 {
os.Exit(exitCode)
}
},
}
var scanGitChangesCmd = &cobra.Command{
Use: "git-changes",
Short: "Scan for secrets in uncommitted changes in a git repo",
Run: func(cmd *cobra.Command, args []string) {
initScanConfig(cmd)
var vc config.ViperConfig
if err := viper.Unmarshal(&vc); err != nil {
log.Fatal().Err(err).Msg("Failed to load config")
}
cfg, err := vc.Translate()
if err != nil {
log.Fatal().Err(err).Msg("Failed to load config")
}
cfg.Path, _ = cmd.Flags().GetString("config")
exitCode, _ := cmd.Flags().GetInt("exit-code")
staged, _ := cmd.Flags().GetBool("staged")
start := time.Now()
// Setup detector
detector := detect.NewDetector(cfg)
detector.Config.Path, err = cmd.Flags().GetString("config")
if err != nil {
log.Fatal().Err(err).Msg("")
}
source, err := cmd.Flags().GetString("source")
if err != nil {
log.Fatal().Err(err).Msg("")
}
// if config path is not set, then use the {source}/.gitleaks.toml path.
// note that there may not be a `{source}/.gitleaks.toml` file, this is ok.
if detector.Config.Path == "" {
detector.Config.Path = filepath.Join(source, ".gitleaks.toml")
}
// set verbose flag
if detector.Verbose, err = cmd.Flags().GetBool("verbose"); err != nil {
log.Fatal().Err(err).Msg("")
}
// set redact flag
if detector.Redact, err = cmd.Flags().GetBool("redact"); err != nil {
log.Fatal().Err(err).Msg("")
}
if detector.MaxTargetMegaBytes, err = cmd.Flags().GetInt("max-target-megabytes"); err != nil {
log.Fatal().Err(err).Msg("")
}
// set color flag
if detector.NoColor, err = cmd.Flags().GetBool("no-color"); err != nil {
log.Fatal().Err(err).Msg("")
}
if fileExists(filepath.Join(source, ".infisicalignore")) {
if err = detector.AddGitleaksIgnore(filepath.Join(source, ".infisicalignore")); err != nil {
log.Fatal().Err(err).Msg("could not call AddInfisicalIgnore")
}
}
// get log options for git scan
logOpts, err := cmd.Flags().GetString("log-opts")
if err != nil {
log.Fatal().Err(err).Msg("")
}
// start git scan
var findings []report.Finding
if staged {
findings, err = detector.DetectGit(source, logOpts, detect.ProtectStagedType)
} else {
findings, err = detector.DetectGit(source, logOpts, detect.ProtectType)
}
if err != nil {
// don't exit on error, just log it
log.Error().Err(err).Msg("")
}
// log info about the scan
log.Info().Msgf("scan completed in %s", FormatDuration(time.Since(start)))
if len(findings) != 0 {
log.Warn().Msgf("leaks found: %d", len(findings))
} else {
log.Info().Msg("no leaks found")
}
reportPath, _ := cmd.Flags().GetString("report-path")
ext, _ := cmd.Flags().GetString("report-format")
if reportPath != "" {
if err = report.Write(findings, cfg, ext, reportPath); err != nil {
log.Fatal().Err(err).Msg("")
}
}
if len(findings) != 0 {
os.Exit(exitCode)
}
},
}
func fileExists(fileName string) bool {
// check for a .gitleaksignore file
info, err := os.Stat(fileName)
if err != nil && !os.IsNotExist(err) {
return false
}
if info != nil && err == nil {
if !info.IsDir() {
return true
}
}
return false
}
func FormatDuration(d time.Duration) string {
scale := 100 * time.Second
// look for the max scale that is smaller than d
for scale > d {
scale = scale / 10
}
return d.Round(scale / 100).String()
}

@ -22,112 +22,101 @@
package report
import (
"fmt"
"os"
"path/filepath"
"strings"
"testing"
"github.com/Infisical/infisical-merge/config"
"github.com/spf13/viper"
)
const configPath = "../testdata/config/"
func TestWriteSarif(t *testing.T) {
tests := []struct {
findings []Finding
testReportName string
expected string
wantEmpty bool
cfgName string
}{
{
cfgName: "simple",
testReportName: "simple",
expected: filepath.Join(expectPath, "report", "sarif_simple.sarif"),
findings: []Finding{
{
// func TestWriteSarif(t *testing.T) {
// tests := []struct {
// findings []Finding
// testReportName string
// expected string
// wantEmpty bool
// cfgName string
// }{
// {
// cfgName: "simple",
// testReportName: "simple",
// expected: filepath.Join(expectPath, "report", "sarif_simple.sarif"),
// findings: []Finding{
// {
Description: "A test rule",
RuleID: "test-rule",
Match: "line containing secret",
Secret: "a secret",
StartLine: 1,
EndLine: 2,
StartColumn: 1,
EndColumn: 2,
Message: "opps",
File: "auth.py",
Commit: "0000000000000000",
Author: "John Doe",
Email: "johndoe@gmail.com",
Date: "10-19-2003",
Tags: []string{},
},
}},
}
// Description: "A test rule",
// RuleID: "test-rule",
// Match: "line containing secret",
// Secret: "a secret",
// StartLine: 1,
// EndLine: 2,
// StartColumn: 1,
// EndColumn: 2,
// Message: "opps",
// File: "auth.py",
// Commit: "0000000000000000",
// Author: "John Doe",
// Email: "johndoe@gmail.com",
// Date: "10-19-2003",
// Tags: []string{},
// },
// }},
// }
for _, test := range tests {
// create tmp file using os.TempDir()
tmpfile, err := os.Create(filepath.Join(tmpPath, test.testReportName+".json"))
if err != nil {
os.Remove(tmpfile.Name())
t.Error(err)
}
viper.Reset()
viper.AddConfigPath(configPath)
viper.SetConfigName(test.cfgName)
viper.SetConfigType("toml")
err = viper.ReadInConfig()
if err != nil {
t.Error(err)
}
// for _, test := range tests {
// // create tmp file using os.TempDir()
// tmpfile, err := os.Create(filepath.Join(tmpPath, test.testReportName+".json"))
// if err != nil {
// os.Remove(tmpfile.Name())
// t.Error(err)
// }
// viper.Reset()
// viper.AddConfigPath(configPath)
// viper.SetConfigName(test.cfgName)
// viper.SetConfigType("toml")
// err = viper.ReadInConfig()
// if err != nil {
// t.Error(err)
// }
var vc config.ViperConfig
err = viper.Unmarshal(&vc)
if err != nil {
t.Error(err)
}
// var vc config.ViperConfig
// err = viper.Unmarshal(&vc)
// if err != nil {
// t.Error(err)
// }
cfg, err := vc.Translate()
if err != nil {
t.Error(err)
}
err = writeSarif(cfg, test.findings, tmpfile)
fmt.Println(cfg)
if err != nil {
os.Remove(tmpfile.Name())
t.Error(err)
}
got, err := os.ReadFile(tmpfile.Name())
if err != nil {
os.Remove(tmpfile.Name())
t.Error(err)
}
if test.wantEmpty {
if len(got) > 0 {
os.Remove(tmpfile.Name())
t.Errorf("Expected empty file, got %s", got)
}
os.Remove(tmpfile.Name())
continue
}
want, err := os.ReadFile(test.expected)
if err != nil {
os.Remove(tmpfile.Name())
t.Error(err)
}
// cfg, err := vc.Translate()
// if err != nil {
// t.Error(err)
// }
// err = writeSarif(cfg, test.findings, tmpfile)
// fmt.Println(cfg)
// if err != nil {
// os.Remove(tmpfile.Name())
// t.Error(err)
// }
// got, err := os.ReadFile(tmpfile.Name())
// if err != nil {
// os.Remove(tmpfile.Name())
// t.Error(err)
// }
// if test.wantEmpty {
// if len(got) > 0 {
// os.Remove(tmpfile.Name())
// t.Errorf("Expected empty file, got %s", got)
// }
// os.Remove(tmpfile.Name())
// continue
// }
// want, err := os.ReadFile(test.expected)
// if err != nil {
// os.Remove(tmpfile.Name())
// t.Error(err)
// }
if string(got) != string(want) {
err = os.WriteFile(strings.Replace(test.expected, ".sarif", ".got.sarif", 1), got, 0644)
if err != nil {
t.Error(err)
}
t.Errorf("got %s, want %s", string(got), string(want))
}
// if string(got) != string(want) {
// err = os.WriteFile(strings.Replace(test.expected, ".sarif", ".got.sarif", 1), got, 0644)
// if err != nil {
// t.Error(err)
// }
// t.Errorf("got %s, want %s", string(got), string(want))
// }
os.Remove(tmpfile.Name())
}
}
// os.Remove(tmpfile.Name())
// }
// }

@ -0,0 +1,2 @@
RuleID,Commit,File,Secret,Match,StartLine,EndLine,StartColumn,EndColumn,Author,Message,Date,Email,Fingerprint
1,b,c,f,s,m,s,e,s,e,a,m,f,r,f
1 RuleID,Commit,File,Secret,Match,StartLine,EndLine,StartColumn,EndColumn,Author,Message,Date,Email,Fingerprint
2 1,b,c,f,s,m,s,e,s,e,a,m,f,r,f

@ -0,0 +1,40 @@
[
{
"Description": "PyPI upload token",
"StartLine": 32,
"EndLine": 32,
"StartColumn": 21,
"EndColumn": 106,
"Match": "************************",
"Secret": "************************",
"File": "detect/detect_test.go",
"Commit": "9326f35380636bcbe61e94b0584d1618c4b5c2c2",
"Entropy": 1.9606875,
"Author": "****",
"Email": "****",
"Date": "2022-03-07T14:33:06Z",
"Message": "Escape - character in regex character groups (#802)\n\n* fix char escape\n\n* add test\n\n* fix verbosity in make test",
"Tags": [],
"RuleID": "pypi-upload-token",
"Fingerprint": "9326f35380636bcbe61e94b0584d1618c4b5c2c2:detect/detect_test.go:pypi-upload-token:32"
},
{
"Description": "PyPI upload token",
"StartLine": 33,
"EndLine": 33,
"StartColumn": 21,
"EndColumn": 106,
"Match": "************************",
"Secret": "************************",
"File": "detect/detect_test.go",
"Commit": "9326f35380636bcbe61e94b0584d1618c4b5c2c2",
"Entropy": 1.9606875,
"Author": "****",
"Email": "****",
"Date": "2022-03-07T14:33:06Z",
"Message": "Escape - character in regex character groups (#802)\n\n* fix char escape\n\n* add test\n\n* fix verbosity in make test",
"Tags": [],
"RuleID": "pypi-upload-token",
"Fingerprint": "9326f35380636bcbe61e94b0584d1618c4b5c2c2:detect/detect_test.go:pypi-upload-token:33"
}
]

@ -0,0 +1,6 @@
{
"$schema": "https://json.schemastore.org/sarif-2.1.0.json",
"version": "2.1.0",
"runs": [
]
}

@ -0,0 +1,9 @@
title = "simple config with allowlist for aws"
[[rules]]
description = "AWS Access Key"
id = "aws-access-key"
regex = '''(A3T[A-Z0-9]|AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{16}'''
tags = ["key", "AWS"]
[rules.allowlist]
regexes = ['''AKIALALEMEL33243OLIA''']

@ -0,0 +1,9 @@
title = "simple config with allowlist for a specific commit"
[[rules]]
description = "AWS Access Key"
id = "aws-access-key"
regex = '''(A3T[A-Z0-9]|AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{16}'''
tags = ["key", "AWS"]
[rules.allowlist]
commits = ['''allowthiscommit''']

@ -0,0 +1,8 @@
[[rules]]
description = "AWS Access Key"
id = "aws-access-key"
regex = '''(A3T[A-Z0-9]|AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{16}'''
tags = ["key", "AWS"]
[allowlist]
regexes = ['''AKIALALEMEL33243OLIA''']

@ -0,0 +1,9 @@
title = "simple config with allowlist for .go files"
[[rules]]
description = "AWS Access Key"
id = "aws-access-key"
regex = '''(A3T[A-Z0-9]|AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{16}'''
tags = ["key", "AWS"]
[rules.allowlist]
paths = ['''.go''']

@ -0,0 +1,8 @@
title = "gitleaks config"
[[rules]]
id = "discord-api-key"
description = "Discord API key"
regex = '''(?i)(discord[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([a-h0-9]{64})['\"]'''
secretGroup = 5
entropy = 3.5

@ -0,0 +1,10 @@
title = "gitleaks config"
[extend]
path="../testdata/config/extend_1.toml"
[[rules]]
description = "AWS Secret Key"
id = "aws-secret-key"
regex = '''(?i)aws_(.{0,20})?=?.[\'\"0-9a-zA-Z\/+]{40}'''
tags = ["key", "AWS"]

@ -0,0 +1,8 @@
title = "gitleaks config"
[[rules]]
id = "discord-api-key"
description = "Discord API key"
regex = '''(?i)(discord[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([a-h0-9]{64})['\"]'''
secretGroup = 3
entropy = 3.5

@ -0,0 +1,8 @@
title = "gitleaks config"
# https://learnxinyminutes.com/docs/toml/ for toml reference
[[rules]]
id = "pypi-upload-token"
description = "PyPI upload token"
regex = '''pypi-AgEIcHlwaS5vcmc[A-Za-z0-9\-_]{50,1000}'''
tags = ["key", "pypi"]

@ -0,0 +1,10 @@
title = "gitleaks extended 1"
[extend]
path="../testdata/config/extend_2.toml"
[[rules]]
description = "AWS Access Key"
id = "aws-access-key"
regex = '''(A3T[A-Z0-9]|AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{16}'''
tags = ["key", "AWS"]

@ -0,0 +1,10 @@
title = "gitleaks extended 2"
[extend]
path="../testdata/config/extend_3.toml"
[[rules]]
description = "AWS Secret Key"
id = "aws-secret-key-again"
regex = '''(?i)aws_(.{0,20})?=?.[\'\"0-9a-zA-Z\/+]{40}'''
tags = ["key", "AWS"]

@ -0,0 +1,9 @@
title = "gitleaks extended 3"
## This should not be loaded since we can only extend configs to a depth of 3
[[rules]]
description = "AWS Secret Key"
id = "aws-secret-key-again-again"
regex = '''(?i)aws_(.{0,20})?=?.[\'\"0-9a-zA-Z\/+]{40}'''
tags = ["key", "AWS"]

@ -0,0 +1,8 @@
title = "gitleaks config"
[[rules]]
description = "Generic API Key"
id = "generic-api-key"
regex = '''(?i)((key|api|token|secret|password)[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([0-9a-zA-Z\-_=]{8,64})['\"]'''
entropy = 3.7
secretGroup = 4

@ -0,0 +1,36 @@
title = "gitleaks config"
[[rules]]
description = "Generic API Key"
id = "generic-api-key"
regex = '''(?i)((key|api|token|secret|password)[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([0-9a-zA-Z\-_=]{8,64})['\"]'''
path = '''.py'''
entropy = 3.7
secretGroup = 4
[allowlist]
description = "global allow lists"
regexes = [
'''219-09-9999''',
'''078-05-1120''',
'''(9[0-9]{2}|666)-\d{2}-\d{4}''',
'''process''',
'''getenv''',
'''\.env''',
'''env\(''',
'''env\.''',
'''setting''',
'''load''',
'''token''',
'''password''',
'''secret''',
'''api\_key''',
'''apikey''',
'''api\-key''',
]
paths = [
'''gitleaks.toml''',
'''(.*?)(jpg|gif|doc|pdf|bin|svg|socket)$''',
'''(go.mod|go.sum)$'''
]

@ -0,0 +1,6 @@
title = "gitleaks config"
[[rules]]
description = "Python Files"
id = "python-files-only"
path = '''.py'''

@ -0,0 +1,222 @@
title = "gitleaks config"
# https://learnxinyminutes.com/docs/toml/ for toml reference
[[rules]]
description = "AWS Access Key"
id = "aws-access-key"
regex = '''(A3T[A-Z0-9]|AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{16}'''
tags = ["key", "AWS"]
[[rules]]
description = "AWS Secret Key"
id = "aws-secret-key"
regex = '''(?i)aws_(.{0,20})?=?.[\'\"0-9a-zA-Z\/+]{40}'''
tags = ["key", "AWS"]
[[rules]]
description = "AWS MWS key"
id = "aws-mws-key"
regex = '''amzn\.mws\.[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}'''
tags = ["key", "AWS", "MWS"]
[[rules]]
description = "Facebook Secret Key"
id = "facebook-secret-key"
regex = '''(?i)(facebook|fb)(.{0,20})?(?-i)['\"][0-9a-f]{32}['\"]'''
tags = ["key", "Facebook"]
[[rules]]
description = "Facebook Client ID"
id = "facebook-client-id"
regex = '''(?i)(facebook|fb)(.{0,20})?['\"][0-9]{13,17}['\"]'''
tags = ["key", "Facebook"]
[[rules]]
description = "Twitter Secret Key"
id = "twitter-secret-key"
regex = '''(?i)twitter(.{0,20})?['\"][0-9a-z]{35,44}['\"]'''
tags = ["key", "Twitter"]
[[rules]]
description = "Twitter Client ID"
id = "twitter-client-id"
regex = '''(?i)twitter(.{0,20})?['\"][0-9a-z]{18,25}['\"]'''
tags = ["client", "Twitter"]
[[rules]]
description = "Github Personal Access Token"
id = "github-pat"
regex = '''ghp_[0-9a-zA-Z]{36}'''
tags = ["key", "Github"]
[[rules]]
description = "Github OAuth Access Token"
id = "github-oauth"
regex = '''gho_[0-9a-zA-Z]{36}'''
tags = ["key", "Github"]
[[rules]]
id = "github-app"
description = "Github App Token"
regex = '''(ghu|ghs)_[0-9a-zA-Z]{36}'''
tags = ["key", "Github"]
[[rules]]
id = "github-refresh"
description = "Github Refresh Token"
regex = '''ghr_[0-9a-zA-Z]{76}'''
tags = ["key", "Github"]
[[rules]]
id = "linkedin-client"
description = "LinkedIn Client ID"
regex = '''(?i)linkedin(.{0,20})?(?-i)[0-9a-z]{12}'''
tags = ["client", "LinkedIn"]
[[rules]]
id = "linkedin-secret"
description = "LinkedIn Secret Key"
regex = '''(?i)linkedin(.{0,20})?[0-9a-z]{16}'''
tags = ["secret", "LinkedIn"]
[[rules]]
id = "slack"
description = "Slack"
regex = '''xox[baprs]-([0-9a-zA-Z]{10,48})?'''
tags = ["key", "Slack"]
[[rules]]
id = "apkey"
description = "Asymmetric Private Key"
regex = '''-----BEGIN ((EC|PGP|DSA|RSA|OPENSSH) )?PRIVATE KEY( BLOCK)?-----'''
tags = ["key", "AsymmetricPrivateKey"]
[[rules]]
id = "google"
description = "Google API key"
regex = '''AIza[0-9A-Za-z\-_]{35}'''
tags = ["key", "Google"]
[[rules]]
id = "google"
description = "Google (GCP) Service Account"
regex = '''"type": "service_account"'''
tags = ["key", "Google"]
[[rules]]
id = "heroku"
description = "Heroku API key"
regex = '''(?i)heroku(.{0,20})?[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}'''
tags = ["key", "Heroku"]
[[rules]]
id = "mailchimp"
description = "MailChimp API key"
regex = '''(?i)(mailchimp|mc)(.{0,20})?[0-9a-f]{32}-us[0-9]{1,2}'''
tags = ["key", "Mailchimp"]
[[rules]]
id = "mailgun"
description = "Mailgun API key"
regex = '''((?i)(mailgun|mg)(.{0,20})?)?key-[0-9a-z]{32}'''
tags = ["key", "Mailgun"]
[[rules]]
id = "paypal"
description = "PayPal Braintree access token"
regex = '''access_token\$production\$[0-9a-z]{16}\$[0-9a-f]{32}'''
tags = ["key", "Paypal"]
[[rules]]
id = "piacatic"
description = "Picatic API key"
regex = '''sk_live_[0-9a-z]{32}'''
tags = ["key", "Picatic"]
[[rules]]
id = "sendgrid"
description = "SendGrid API Key"
regex = '''SG\.[\w_]{16,32}\.[\w_]{16,64}'''
tags = ["key", "SendGrid"]
[[rules]]
description = "Sidekiq Secret"
id = "sidekiq-secret"
regex = '''(?i)(?:BUNDLE_ENTERPRISE__CONTRIBSYS__COM|BUNDLE_GEMS__CONTRIBSYS__COM)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-f0-9]{8}:[a-f0-9]{8})(?:['|\"|\n|\r|\s|\x60|;]|$)'''
secretGroup = 1
keywords = [
"bundle_enterprise__contribsys__com","bundle_gems__contribsys__com",
]
[[rules]]
description = "Sidekiq Sensitive URL"
id = "sidekiq-sensitive-url"
regex = '''(?i)\b(http(?:s??):\/\/)([a-f0-9]{8}:[a-f0-9]{8})@(?:gems.contribsys.com|enterprise.contribsys.com)(?:[\/|\#|\?|:]|$)'''
secretGroup = 2
keywords = [
"gems.contribsys.com","enterprise.contribsys.com",
]
[[rules]]
id = "slack-webhook"
description = "Slack Webhook"
regex = '''https://hooks.slack.com/services/T[a-zA-Z0-9_]{8}/B[a-zA-Z0-9_]{8,12}/[a-zA-Z0-9_]{24}'''
tags = ["key", "slack"]
[[rules]]
id = "stripe"
description = "Stripe API key"
regex = '''(?i)stripe(.{0,20})?[sr]k_live_[0-9a-zA-Z]{24}'''
tags = ["key", "Stripe"]
[[rules]]
id = "square"
description = "Square access token"
regex = '''sq0atp-[0-9A-Za-z\-_]{22}'''
tags = ["key", "square"]
[[rules]]
id = "square-oauth"
description = "Square OAuth secret"
regex = '''sq0csp-[0-9A-Za-z\-_]{43}'''
tags = ["key", "square"]
[[rules]]
id = "twilio"
description = "Twilio API key"
regex = '''(?i)twilio(.{0,20})?SK[0-9a-f]{32}'''
tags = ["key", "twilio"]
[[rules]]
id = "dynatrace"
description = "Dynatrace ttoken"
regex = '''dt0[a-zA-Z]{1}[0-9]{2}\.[A-Z0-9]{24}\.[A-Z0-9]{64}'''
tags = ["key", "Dynatrace"]
[[rules]]
id = "shopify"
description = "Shopify shared secret"
regex = '''shpss_[a-fA-F0-9]{32}'''
tags = ["key", "Shopify"]
[[rules]]
id = "shopify-access"
description = "Shopify access token"
regex = '''shpat_[a-fA-F0-9]{32}'''
tags = ["key", "Shopify"]
[[rules]]
id = "shopify-custom"
description = "Shopify custom app access token"
regex = '''shpca_[a-fA-F0-9]{32}'''
tags = ["key", "Shopify"]
[[rules]]
id = "shopify-private"
description = "Shopify private app access token"
regex = '''shppa_[a-fA-F0-9]{32}'''
tags = ["key", "Shopify"]
[[rules]]
id = "pypi"
description = "PyPI upload token"
regex = '''pypi-AgEIcHlwaS5vcmc[A-Za-z0-9-_]{50,1000}'''
tags = ["key", "pypi"]

@ -0,0 +1,17 @@
import (
"fmt"
"os"
)
// seems safer
aws_token := os.Getenv("AWS_TOKEN")
package foo
import "fmt"
func Foo() {
fmt.Println("foo")
// seems safe
aws_token := "AKIALALEMEL33243OLIA"
fmt.Println(aws_token)
}

@ -0,0 +1,67 @@
import (
"fmt"
"os"
)
// seems safer
aws_token := os.Getenv("AWS_TOKEN")
package foo
import "fmt"
func Foo() {
fmt.Println("foo")
// seems safe
aws_token := "AKIALALEMEL33243OLIA"
fmt.Println(aws_token)
}
package api
import "fmt"
func PrintHello() {
fmt.Println("hello")
}
import (
"fmt"
"os"
)
var a = "initial"
fmt.Println(a)
var b, c int = 1, 2
fmt.Println(b, c)
var d = true
fmt.Println(d)
var e int
fmt.Println(e)
// load secret via env
awsToken := os.Getenv("AWS_TOKEN")
f := "apple"
fmt.Println(f)
// opps I added a secret at line 20
awsToken := "AKIALALEMEL33243OLIA"
package main
import "fmt"
func main() {
var a = "initial"
fmt.Println(a)
var b, c int = 1, 2
fmt.Println(b, c)
var d = true
fmt.Println(d)
var e int
fmt.Println(e)
f := "apple"
fmt.Println(f)
}
# test
This is a repo used for testing gitleaks

@ -0,0 +1,2 @@
RuleID,Commit,File,SymlinkFile,Secret,Match,StartLine,EndLine,StartColumn,EndColumn,Author,Message,Date,Email,Fingerprint
test-rule,0000000000000000,auth.py,,a secret,line containing secret,1,2,1,2,John Doe,opps,10-19-2003,johndoe@gmail.com,fingerprint
1 RuleID Commit File SymlinkFile Secret Match StartLine EndLine StartColumn EndColumn Author Message Date Email Fingerprint
2 test-rule 0000000000000000 auth.py a secret line containing secret 1 2 1 2 John Doe opps 10-19-2003 johndoe@gmail.com fingerprint

@ -0,0 +1,22 @@
[
{
"Description": "",
"StartLine": 1,
"EndLine": 2,
"StartColumn": 1,
"EndColumn": 2,
"Match": "line containing secret",
"Secret": "a secret",
"File": "auth.py",
"SymlinkFile": "",
"Commit": "0000000000000000",
"Entropy": 0,
"Author": "John Doe",
"Email": "johndoe@gmail.com",
"Date": "10-19-2003",
"Message": "opps",
"Tags": [],
"RuleID": "test-rule",
"Fingerprint": ""
}
]

@ -0,0 +1,302 @@
{
"$schema": "https://json.schemastore.org/sarif-2.1.0.json",
"version": "2.1.0",
"runs": [
{
"tool": {
"driver": {
"name": "gitleaks",
"semanticVersion": "v8.0.0",
"informationUri": "https://github.com/Infisical/infisical",
"rules": [
{
"id": "aws-access-key",
"name": "AWS Access Key",
"shortDescription": {
"text": "(A3T[A-Z0-9]|AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{16}"
}
},
{
"id": "aws-secret-key",
"name": "AWS Secret Key",
"shortDescription": {
"text": "(?i)aws_(.{0,20})?=?.[\\'\\\"0-9a-zA-Z\\/+]{40}"
}
},
{
"id": "aws-mws-key",
"name": "AWS MWS key",
"shortDescription": {
"text": "amzn\\.mws\\.[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"
}
},
{
"id": "facebook-secret-key",
"name": "Facebook Secret Key",
"shortDescription": {
"text": "(?i)(facebook|fb)(.{0,20})?(?-i)['\\\"][0-9a-f]{32}['\\\"]"
}
},
{
"id": "facebook-client-id",
"name": "Facebook Client ID",
"shortDescription": {
"text": "(?i)(facebook|fb)(.{0,20})?['\\\"][0-9]{13,17}['\\\"]"
}
},
{
"id": "twitter-secret-key",
"name": "Twitter Secret Key",
"shortDescription": {
"text": "(?i)twitter(.{0,20})?['\\\"][0-9a-z]{35,44}['\\\"]"
}
},
{
"id": "twitter-client-id",
"name": "Twitter Client ID",
"shortDescription": {
"text": "(?i)twitter(.{0,20})?['\\\"][0-9a-z]{18,25}['\\\"]"
}
},
{
"id": "github-pat",
"name": "Github Personal Access Token",
"shortDescription": {
"text": "ghp_[0-9a-zA-Z]{36}"
}
},
{
"id": "github-oauth",
"name": "Github OAuth Access Token",
"shortDescription": {
"text": "gho_[0-9a-zA-Z]{36}"
}
},
{
"id": "github-app",
"name": "Github App Token",
"shortDescription": {
"text": "(ghu|ghs)_[0-9a-zA-Z]{36}"
}
},
{
"id": "github-refresh",
"name": "Github Refresh Token",
"shortDescription": {
"text": "ghr_[0-9a-zA-Z]{76}"
}
},
{
"id": "linkedin-client",
"name": "LinkedIn Client ID",
"shortDescription": {
"text": "(?i)linkedin(.{0,20})?(?-i)[0-9a-z]{12}"
}
},
{
"id": "linkedin-secret",
"name": "LinkedIn Secret Key",
"shortDescription": {
"text": "(?i)linkedin(.{0,20})?[0-9a-z]{16}"
}
},
{
"id": "slack",
"name": "Slack",
"shortDescription": {
"text": "xox[baprs]-([0-9a-zA-Z]{10,48})?"
}
},
{
"id": "apkey",
"name": "Asymmetric Private Key",
"shortDescription": {
"text": "-----BEGIN ((EC|PGP|DSA|RSA|OPENSSH) )?PRIVATE KEY( BLOCK)?-----"
}
},
{
"id": "google",
"name": "Google (GCP) Service Account",
"shortDescription": {
"text": "\"type\": \"service_account\""
}
},
{
"id": "google",
"name": "Google (GCP) Service Account",
"shortDescription": {
"text": "\"type\": \"service_account\""
}
},
{
"id": "heroku",
"name": "Heroku API key",
"shortDescription": {
"text": "(?i)heroku(.{0,20})?[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"
}
},
{
"id": "mailchimp",
"name": "MailChimp API key",
"shortDescription": {
"text": "(?i)(mailchimp|mc)(.{0,20})?[0-9a-f]{32}-us[0-9]{1,2}"
}
},
{
"id": "mailgun",
"name": "Mailgun API key",
"shortDescription": {
"text": "((?i)(mailgun|mg)(.{0,20})?)?key-[0-9a-z]{32}"
}
},
{
"id": "paypal",
"name": "PayPal Braintree access token",
"shortDescription": {
"text": "access_token\\$production\\$[0-9a-z]{16}\\$[0-9a-f]{32}"
}
},
{
"id": "piacatic",
"name": "Picatic API key",
"shortDescription": {
"text": "sk_live_[0-9a-z]{32}"
}
},
{
"id": "sendgrid",
"name": "SendGrid API Key",
"shortDescription": {
"text": "SG\\.[\\w_]{16,32}\\.[\\w_]{16,64}"
}
},
{
"id": "sidekiq-secret",
"name": "Sidekiq Secret",
"shortDescription": {
"text": "(?i)(?:BUNDLE_ENTERPRISE__CONTRIBSYS__COM|BUNDLE_GEMS__CONTRIBSYS__COM)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|\u003e|:=|\\|\\|:|\u003c=|=\u003e|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-f0-9]{8}:[a-f0-9]{8})(?:['|\\\"|\\n|\\r|\\s|\\x60|;]|$)"
}
},
{
"id": "sidekiq-sensitive-url",
"name": "Sidekiq Sensitive URL",
"shortDescription": {
"text": "(?i)\\b(http(?:s??):\\/\\/)([a-f0-9]{8}:[a-f0-9]{8})@(?:gems.contribsys.com|enterprise.contribsys.com)(?:[\\/|\\#|\\?|:]|$)"
}
},
{
"id": "slack-webhook",
"name": "Slack Webhook",
"shortDescription": {
"text": "https://hooks.slack.com/services/T[a-zA-Z0-9_]{8}/B[a-zA-Z0-9_]{8,12}/[a-zA-Z0-9_]{24}"
}
},
{
"id": "stripe",
"name": "Stripe API key",
"shortDescription": {
"text": "(?i)stripe(.{0,20})?[sr]k_live_[0-9a-zA-Z]{24}"
}
},
{
"id": "square",
"name": "Square access token",
"shortDescription": {
"text": "sq0atp-[0-9A-Za-z\\-_]{22}"
}
},
{
"id": "square-oauth",
"name": "Square OAuth secret",
"shortDescription": {
"text": "sq0csp-[0-9A-Za-z\\-_]{43}"
}
},
{
"id": "twilio",
"name": "Twilio API key",
"shortDescription": {
"text": "(?i)twilio(.{0,20})?SK[0-9a-f]{32}"
}
},
{
"id": "dynatrace",
"name": "Dynatrace ttoken",
"shortDescription": {
"text": "dt0[a-zA-Z]{1}[0-9]{2}\\.[A-Z0-9]{24}\\.[A-Z0-9]{64}"
}
},
{
"id": "shopify",
"name": "Shopify shared secret",
"shortDescription": {
"text": "shpss_[a-fA-F0-9]{32}"
}
},
{
"id": "shopify-access",
"name": "Shopify access token",
"shortDescription": {
"text": "shpat_[a-fA-F0-9]{32}"
}
},
{
"id": "shopify-custom",
"name": "Shopify custom app access token",
"shortDescription": {
"text": "shpca_[a-fA-F0-9]{32}"
}
},
{
"id": "shopify-private",
"name": "Shopify private app access token",
"shortDescription": {
"text": "shppa_[a-fA-F0-9]{32}"
}
},
{
"id": "pypi",
"name": "PyPI upload token",
"shortDescription": {
"text": "pypi-AgEIcHlwaS5vcmc[A-Za-z0-9-_]{50,1000}"
}
}
]
}
},
"results": [
{
"message": {
"text": "test-rule has detected secret for file auth.py at commit 0000000000000000."
},
"ruleId": "test-rule",
"locations": [
{
"physicalLocation": {
"artifactLocation": {
"uri": "auth.py"
},
"region": {
"startLine": 1,
"startColumn": 1,
"endLine": 2,
"endColumn": 2,
"snippet": {
"text": "a secret"
}
}
}
}
],
"partialFingerprints": {
"commitSha": "0000000000000000",
"email": "johndoe@gmail.com",
"author": "John Doe",
"date": "10-19-2003",
"commitMessage": "opps"
}
}
]
}
]
}

@ -0,0 +1,302 @@
{
"$schema": "https://json.schemastore.org/sarif-2.1.0.json",
"version": "2.1.0",
"runs": [
{
"tool": {
"driver": {
"name": "gitleaks",
"semanticVersion": "v8.0.0",
"informationUri": "https://github.com/gitleaks/gitleaks",
"rules": [
{
"id": "aws-access-key",
"name": "AWS Access Key",
"shortDescription": {
"text": "(A3T[A-Z0-9]|AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{16}"
}
},
{
"id": "aws-secret-key",
"name": "AWS Secret Key",
"shortDescription": {
"text": "(?i)aws_(.{0,20})?=?.[\\'\\\"0-9a-zA-Z\\/+]{40}"
}
},
{
"id": "aws-mws-key",
"name": "AWS MWS key",
"shortDescription": {
"text": "amzn\\.mws\\.[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"
}
},
{
"id": "facebook-secret-key",
"name": "Facebook Secret Key",
"shortDescription": {
"text": "(?i)(facebook|fb)(.{0,20})?(?-i)['\\\"][0-9a-f]{32}['\\\"]"
}
},
{
"id": "facebook-client-id",
"name": "Facebook Client ID",
"shortDescription": {
"text": "(?i)(facebook|fb)(.{0,20})?['\\\"][0-9]{13,17}['\\\"]"
}
},
{
"id": "twitter-secret-key",
"name": "Twitter Secret Key",
"shortDescription": {
"text": "(?i)twitter(.{0,20})?['\\\"][0-9a-z]{35,44}['\\\"]"
}
},
{
"id": "twitter-client-id",
"name": "Twitter Client ID",
"shortDescription": {
"text": "(?i)twitter(.{0,20})?['\\\"][0-9a-z]{18,25}['\\\"]"
}
},
{
"id": "github-pat",
"name": "Github Personal Access Token",
"shortDescription": {
"text": "ghp_[0-9a-zA-Z]{36}"
}
},
{
"id": "github-oauth",
"name": "Github OAuth Access Token",
"shortDescription": {
"text": "gho_[0-9a-zA-Z]{36}"
}
},
{
"id": "github-app",
"name": "Github App Token",
"shortDescription": {
"text": "(ghu|ghs)_[0-9a-zA-Z]{36}"
}
},
{
"id": "github-refresh",
"name": "Github Refresh Token",
"shortDescription": {
"text": "ghr_[0-9a-zA-Z]{76}"
}
},
{
"id": "linkedin-client",
"name": "LinkedIn Client ID",
"shortDescription": {
"text": "(?i)linkedin(.{0,20})?(?-i)[0-9a-z]{12}"
}
},
{
"id": "linkedin-secret",
"name": "LinkedIn Secret Key",
"shortDescription": {
"text": "(?i)linkedin(.{0,20})?[0-9a-z]{16}"
}
},
{
"id": "slack",
"name": "Slack",
"shortDescription": {
"text": "xox[baprs]-([0-9a-zA-Z]{10,48})?"
}
},
{
"id": "apkey",
"name": "Asymmetric Private Key",
"shortDescription": {
"text": "-----BEGIN ((EC|PGP|DSA|RSA|OPENSSH) )?PRIVATE KEY( BLOCK)?-----"
}
},
{
"id": "google",
"name": "Google (GCP) Service Account",
"shortDescription": {
"text": "\"type\": \"service_account\""
}
},
{
"id": "google",
"name": "Google (GCP) Service Account",
"shortDescription": {
"text": "\"type\": \"service_account\""
}
},
{
"id": "heroku",
"name": "Heroku API key",
"shortDescription": {
"text": "(?i)heroku(.{0,20})?[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"
}
},
{
"id": "mailchimp",
"name": "MailChimp API key",
"shortDescription": {
"text": "(?i)(mailchimp|mc)(.{0,20})?[0-9a-f]{32}-us[0-9]{1,2}"
}
},
{
"id": "mailgun",
"name": "Mailgun API key",
"shortDescription": {
"text": "((?i)(mailgun|mg)(.{0,20})?)?key-[0-9a-z]{32}"
}
},
{
"id": "paypal",
"name": "PayPal Braintree access token",
"shortDescription": {
"text": "access_token\\$production\\$[0-9a-z]{16}\\$[0-9a-f]{32}"
}
},
{
"id": "piacatic",
"name": "Picatic API key",
"shortDescription": {
"text": "sk_live_[0-9a-z]{32}"
}
},
{
"id": "sendgrid",
"name": "SendGrid API Key",
"shortDescription": {
"text": "SG\\.[\\w_]{16,32}\\.[\\w_]{16,64}"
}
},
{
"id": "sidekiq-secret",
"name": "Sidekiq Secret",
"shortDescription": {
"text": "(?i)(?:BUNDLE_ENTERPRISE__CONTRIBSYS__COM|BUNDLE_GEMS__CONTRIBSYS__COM)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|\u003e|:=|\\|\\|:|\u003c=|=\u003e|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-f0-9]{8}:[a-f0-9]{8})(?:['|\\\"|\\n|\\r|\\s|\\x60|;]|$)"
}
},
{
"id": "sidekiq-sensitive-url",
"name": "Sidekiq Sensitive URL",
"shortDescription": {
"text": "(?i)\\b(http(?:s??):\\/\\/)([a-f0-9]{8}:[a-f0-9]{8})@(?:gems.contribsys.com|enterprise.contribsys.com)(?:[\\/|\\#|\\?|:]|$)"
}
},
{
"id": "slack-webhook",
"name": "Slack Webhook",
"shortDescription": {
"text": "https://hooks.slack.com/services/T[a-zA-Z0-9_]{8}/B[a-zA-Z0-9_]{8,12}/[a-zA-Z0-9_]{24}"
}
},
{
"id": "stripe",
"name": "Stripe API key",
"shortDescription": {
"text": "(?i)stripe(.{0,20})?[sr]k_live_[0-9a-zA-Z]{24}"
}
},
{
"id": "square",
"name": "Square access token",
"shortDescription": {
"text": "sq0atp-[0-9A-Za-z\\-_]{22}"
}
},
{
"id": "square-oauth",
"name": "Square OAuth secret",
"shortDescription": {
"text": "sq0csp-[0-9A-Za-z\\-_]{43}"
}
},
{
"id": "twilio",
"name": "Twilio API key",
"shortDescription": {
"text": "(?i)twilio(.{0,20})?SK[0-9a-f]{32}"
}
},
{
"id": "dynatrace",
"name": "Dynatrace ttoken",
"shortDescription": {
"text": "dt0[a-zA-Z]{1}[0-9]{2}\\.[A-Z0-9]{24}\\.[A-Z0-9]{64}"
}
},
{
"id": "shopify",
"name": "Shopify shared secret",
"shortDescription": {
"text": "shpss_[a-fA-F0-9]{32}"
}
},
{
"id": "shopify-access",
"name": "Shopify access token",
"shortDescription": {
"text": "shpat_[a-fA-F0-9]{32}"
}
},
{
"id": "shopify-custom",
"name": "Shopify custom app access token",
"shortDescription": {
"text": "shpca_[a-fA-F0-9]{32}"
}
},
{
"id": "shopify-private",
"name": "Shopify private app access token",
"shortDescription": {
"text": "shppa_[a-fA-F0-9]{32}"
}
},
{
"id": "pypi",
"name": "PyPI upload token",
"shortDescription": {
"text": "pypi-AgEIcHlwaS5vcmc[A-Za-z0-9-_]{50,1000}"
}
}
]
}
},
"results": [
{
"message": {
"text": "test-rule has detected secret for file auth.py at commit 0000000000000000."
},
"ruleId": "test-rule",
"locations": [
{
"physicalLocation": {
"artifactLocation": {
"uri": "auth.py"
},
"region": {
"startLine": 1,
"startColumn": 1,
"endLine": 2,
"endColumn": 2,
"snippet": {
"text": "a secret"
}
}
}
}
],
"partialFingerprints": {
"commitSha": "0000000000000000",
"email": "johndoe@gmail.com",
"author": "John Doe",
"date": "10-19-2003",
"commitMessage": "opps"
}
}
]
}
]
}

@ -0,0 +1,24 @@
package main
import "fmt"
func main() {
var a = "initial"
fmt.Println(a)
var b, c int = 1, 2
fmt.Println(b, c)
var d = true
fmt.Println(d)
var e int
fmt.Println(e)
// opps I added a secret at line 20
awsToken := "AKIALALEMEL33243OLIA"
f := "apple"
fmt.Println(f)
}

@ -0,0 +1,2 @@
# test
This is a repo used for testing gitleaks

@ -0,0 +1,7 @@
package api
import "fmt"
func PrintHello() {
fmt.Println("hello")
}

@ -0,0 +1 @@
removing secret from foo package

@ -0,0 +1 @@
2e1db472eeba53f06c4026ae4566ea022e36598e branch 'main' of github.com:gitleaks/test

@ -0,0 +1 @@
ref: refs/heads/main

@ -0,0 +1 @@
1b6da43b82b22e4eaa10bcf8ee591e91abbfc587

@ -0,0 +1,13 @@
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[remote "origin"]
url = git@github.com:gitleaks/test.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "main"]
remote = origin
merge = refs/heads/main

@ -0,0 +1 @@
Unnamed repository; edit this file 'description' to name the repository.

Binary file not shown.

@ -0,0 +1,6 @@
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~

@ -0,0 +1,13 @@
0000000000000000000000000000000000000000 1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 Zach Rice <zricer@protonmail.com> 1635896329 -0500 clone: from github.com:gitleaks/test.git
1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 Zach Rice <zricer@protonmail.com> 1635896362 -0500 checkout: moving from main to remove-secrets
1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 906335481df9a4b48906c90318b4fac76b67fe73 Zach Rice <zricer@protonmail.com> 1635896426 -0500 commit: load token via env var
906335481df9a4b48906c90318b4fac76b67fe73 a122b33c6bad3ee54724f52f2caad385ab1982ab Zach Rice <zricer@protonmail.com> 1635896518 -0500 commit: add api package
a122b33c6bad3ee54724f52f2caad385ab1982ab a122b33c6bad3ee54724f52f2caad385ab1982ab Zach Rice <zricer@protonmail.com> 1635896543 -0500 checkout: moving from remove-secrets to api-pkg
a122b33c6bad3ee54724f52f2caad385ab1982ab 1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 Zach Rice <zricer@protonmail.com> 1635896644 -0500 checkout: moving from api-pkg to main
1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 2e1db472eeba53f06c4026ae4566ea022e36598e Zach Rice <zricer@protonmail.com> 1635896648 -0500 pull origin main: Fast-forward
2e1db472eeba53f06c4026ae4566ea022e36598e 2e1db472eeba53f06c4026ae4566ea022e36598e Zach Rice <zricer@protonmail.com> 1635896716 -0500 checkout: moving from main to foo
2e1db472eeba53f06c4026ae4566ea022e36598e 491504d5a31946ce75e22554cc34203d8e5ff3ca Zach Rice <zricer@protonmail.com> 1635896886 -0500 commit: adding foo package with secret
491504d5a31946ce75e22554cc34203d8e5ff3ca f1b58b97808f8e744f6a23c693859df5b5968901 Zach Rice <zricer@protonmail.com> 1635896931 -0500 commit: removing secret from foo package
f1b58b97808f8e744f6a23c693859df5b5968901 2e1db472eeba53f06c4026ae4566ea022e36598e Zach Rice <zricer@protonmail.com> 1635897009 -0500 checkout: moving from foo to main
2e1db472eeba53f06c4026ae4566ea022e36598e f1b58b97808f8e744f6a23c693859df5b5968901 Zach Rice <zricer@protonmail.com> 1635897062 -0500 checkout: moving from main to foo
f1b58b97808f8e744f6a23c693859df5b5968901 2e1db472eeba53f06c4026ae4566ea022e36598e Zach Rice <zricer@protonmail.com> 1635897508 -0500 checkout: moving from foo to main

@ -0,0 +1 @@
0000000000000000000000000000000000000000 a122b33c6bad3ee54724f52f2caad385ab1982ab Zach Rice <zricer@protonmail.com> 1635896543 -0500 branch: Created from HEAD

@ -0,0 +1,3 @@
0000000000000000000000000000000000000000 2e1db472eeba53f06c4026ae4566ea022e36598e Zach Rice <zricer@protonmail.com> 1635896716 -0500 branch: Created from HEAD
2e1db472eeba53f06c4026ae4566ea022e36598e 491504d5a31946ce75e22554cc34203d8e5ff3ca Zach Rice <zricer@protonmail.com> 1635896886 -0500 commit: adding foo package with secret
491504d5a31946ce75e22554cc34203d8e5ff3ca f1b58b97808f8e744f6a23c693859df5b5968901 Zach Rice <zricer@protonmail.com> 1635896931 -0500 commit: removing secret from foo package

@ -0,0 +1,2 @@
0000000000000000000000000000000000000000 1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 Zach Rice <zricer@protonmail.com> 1635896329 -0500 clone: from github.com:gitleaks/test.git
1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 2e1db472eeba53f06c4026ae4566ea022e36598e Zach Rice <zricer@protonmail.com> 1635896648 -0500 pull origin main: Fast-forward

@ -0,0 +1,3 @@
0000000000000000000000000000000000000000 1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 Zach Rice <zricer@protonmail.com> 1635896362 -0500 branch: Created from HEAD
1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 906335481df9a4b48906c90318b4fac76b67fe73 Zach Rice <zricer@protonmail.com> 1635896426 -0500 commit: load token via env var
906335481df9a4b48906c90318b4fac76b67fe73 a122b33c6bad3ee54724f52f2caad385ab1982ab Zach Rice <zricer@protonmail.com> 1635896518 -0500 commit: add api package

@ -0,0 +1 @@
0000000000000000000000000000000000000000 1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 Zach Rice <zricer@protonmail.com> 1635896329 -0500 clone: from github.com:gitleaks/test.git

@ -0,0 +1 @@
0000000000000000000000000000000000000000 a122b33c6bad3ee54724f52f2caad385ab1982ab Zach Rice <zricer@protonmail.com> 1635896552 -0500 update by push

@ -0,0 +1 @@
0000000000000000000000000000000000000000 f1b58b97808f8e744f6a23c693859df5b5968901 Zach Rice <zricer@protonmail.com> 1635896935 -0500 update by push

@ -0,0 +1 @@
1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 2e1db472eeba53f06c4026ae4566ea022e36598e Zach Rice <zricer@protonmail.com> 1635896648 -0500 pull origin main: fast-forward

@ -0,0 +1 @@
xUÌ1 Â0`×ܯ8nJ.‚ƒƒ:*(8´\¤´É•$ê þw3 Noxï{Ý$6Ëf1Û~´wF'0øYbF ŠœÏTB<12>p<>ÐãND|ƒ*]uŽCÈSÐT •…ªkLÌ>a²Ž#(ûJm®Ö(©ÚsæðÔ´¹]Úëé°=õ÷ô°ú03

@ -0,0 +1,3 @@
xťŽM
Â0F]çs%™üt
"žÁĄ»I2ˇEŰ”»đôö ®>xĽ_ŞË2w@;śză<C483>ءCŚXŠ§@˛Ö6 5Ź)ÔĆMÖ&†ĚÎF:l'ĚFÇTHÄŹFFĂ1äiPüéSmđä4ÁcN×o;¦Ý·V{]žß—T—<1B>`=ŤÁa€łöZ«<5A>»ü«wĺ ˝ľd…}f<>u‡ťúKKś

@ -0,0 +1,2 @@
# pack-refs with: peeled fully-peeled sorted
1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 refs/remotes/origin/main

@ -0,0 +1 @@
a122b33c6bad3ee54724f52f2caad385ab1982ab

@ -0,0 +1 @@
f1b58b97808f8e744f6a23c693859df5b5968901

@ -0,0 +1 @@
2e1db472eeba53f06c4026ae4566ea022e36598e

@ -0,0 +1 @@
a122b33c6bad3ee54724f52f2caad385ab1982ab

@ -0,0 +1 @@
ref: refs/remotes/origin/main

@ -0,0 +1 @@
a122b33c6bad3ee54724f52f2caad385ab1982ab

@ -0,0 +1 @@
f1b58b97808f8e744f6a23c693859df5b5968901

@ -0,0 +1 @@
2e1db472eeba53f06c4026ae4566ea022e36598e

@ -0,0 +1,27 @@
package main
import (
"fmt"
"os"
)
func main() {
var a = "initial"
fmt.Println(a)
var b, c int = 1, 2
fmt.Println(b, c)
var d = true
fmt.Println(d)
var e int
fmt.Println(e)
// load secret via env
awsToken := os.Getenv("AWS_TOKEN")
f := "apple"
fmt.Println(f)
}

@ -0,0 +1 @@
api/api.go:aws-access-key:6

@ -0,0 +1,2 @@
# test
This is a repo used for testing gitleaks

@ -0,0 +1,10 @@
package api
import "fmt"
func PrintHello() {
aws_token := "AKIALALEMEL33243OLIA" // fingerprint of that secret is added to .gitleaksignore
aws_token2 := "AKIALALEMEL33243OLIA" // this one is not
fmt.Println(aws_token)
fmt.Println(aws_token2)
}

@ -0,0 +1 @@
add .gitleaksignore file

@ -0,0 +1 @@
2e1db472eeba53f06c4026ae4566ea022e36598e branch 'main' of github.com:gitleaks/test

@ -0,0 +1 @@
ref: refs/heads/main

@ -0,0 +1 @@
1b6da43b82b22e4eaa10bcf8ee591e91abbfc587

@ -0,0 +1,13 @@
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[remote "origin"]
url = git@github.com:gitleaks/test.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "main"]
remote = origin
merge = refs/heads/main

@ -0,0 +1 @@
Unnamed repository; edit this file 'description' to name the repository.

Binary file not shown.

@ -0,0 +1,6 @@
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~

@ -0,0 +1,14 @@
0000000000000000000000000000000000000000 1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 Zach Rice <zricer@protonmail.com> 1635896329 -0500 clone: from github.com:gitleaks/test.git
1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 Zach Rice <zricer@protonmail.com> 1635896362 -0500 checkout: moving from main to remove-secrets
1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 906335481df9a4b48906c90318b4fac76b67fe73 Zach Rice <zricer@protonmail.com> 1635896426 -0500 commit: load token via env var
906335481df9a4b48906c90318b4fac76b67fe73 a122b33c6bad3ee54724f52f2caad385ab1982ab Zach Rice <zricer@protonmail.com> 1635896518 -0500 commit: add api package
a122b33c6bad3ee54724f52f2caad385ab1982ab a122b33c6bad3ee54724f52f2caad385ab1982ab Zach Rice <zricer@protonmail.com> 1635896543 -0500 checkout: moving from remove-secrets to api-pkg
a122b33c6bad3ee54724f52f2caad385ab1982ab 1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 Zach Rice <zricer@protonmail.com> 1635896644 -0500 checkout: moving from api-pkg to main
1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 2e1db472eeba53f06c4026ae4566ea022e36598e Zach Rice <zricer@protonmail.com> 1635896648 -0500 pull origin main: Fast-forward
2e1db472eeba53f06c4026ae4566ea022e36598e 2e1db472eeba53f06c4026ae4566ea022e36598e Zach Rice <zricer@protonmail.com> 1635896716 -0500 checkout: moving from main to foo
2e1db472eeba53f06c4026ae4566ea022e36598e 491504d5a31946ce75e22554cc34203d8e5ff3ca Zach Rice <zricer@protonmail.com> 1635896886 -0500 commit: adding foo package with secret
491504d5a31946ce75e22554cc34203d8e5ff3ca f1b58b97808f8e744f6a23c693859df5b5968901 Zach Rice <zricer@protonmail.com> 1635896931 -0500 commit: removing secret from foo package
f1b58b97808f8e744f6a23c693859df5b5968901 2e1db472eeba53f06c4026ae4566ea022e36598e Zach Rice <zricer@protonmail.com> 1635897009 -0500 checkout: moving from foo to main
2e1db472eeba53f06c4026ae4566ea022e36598e f1b58b97808f8e744f6a23c693859df5b5968901 Zach Rice <zricer@protonmail.com> 1635897062 -0500 checkout: moving from main to foo
f1b58b97808f8e744f6a23c693859df5b5968901 2e1db472eeba53f06c4026ae4566ea022e36598e Zach Rice <zricer@protonmail.com> 1635897508 -0500 checkout: moving from foo to main
2e1db472eeba53f06c4026ae4566ea022e36598e bf3f24164d7256b4021575cbdb2f97b98e6f057e Rafael Figueiredo <rfigueiredo@garoa.cloud> 1679239434 -0300 commit: add .gitleaksignore file

@ -0,0 +1 @@
0000000000000000000000000000000000000000 a122b33c6bad3ee54724f52f2caad385ab1982ab Zach Rice <zricer@protonmail.com> 1635896543 -0500 branch: Created from HEAD

@ -0,0 +1,3 @@
0000000000000000000000000000000000000000 2e1db472eeba53f06c4026ae4566ea022e36598e Zach Rice <zricer@protonmail.com> 1635896716 -0500 branch: Created from HEAD
2e1db472eeba53f06c4026ae4566ea022e36598e 491504d5a31946ce75e22554cc34203d8e5ff3ca Zach Rice <zricer@protonmail.com> 1635896886 -0500 commit: adding foo package with secret
491504d5a31946ce75e22554cc34203d8e5ff3ca f1b58b97808f8e744f6a23c693859df5b5968901 Zach Rice <zricer@protonmail.com> 1635896931 -0500 commit: removing secret from foo package

@ -0,0 +1,3 @@
0000000000000000000000000000000000000000 1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 Zach Rice <zricer@protonmail.com> 1635896329 -0500 clone: from github.com:gitleaks/test.git
1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 2e1db472eeba53f06c4026ae4566ea022e36598e Zach Rice <zricer@protonmail.com> 1635896648 -0500 pull origin main: Fast-forward
2e1db472eeba53f06c4026ae4566ea022e36598e bf3f24164d7256b4021575cbdb2f97b98e6f057e Rafael Figueiredo <rfigueiredo@garoa.cloud> 1679239434 -0300 commit: add .gitleaksignore file

@ -0,0 +1,3 @@
0000000000000000000000000000000000000000 1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 Zach Rice <zricer@protonmail.com> 1635896362 -0500 branch: Created from HEAD
1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 906335481df9a4b48906c90318b4fac76b67fe73 Zach Rice <zricer@protonmail.com> 1635896426 -0500 commit: load token via env var
906335481df9a4b48906c90318b4fac76b67fe73 a122b33c6bad3ee54724f52f2caad385ab1982ab Zach Rice <zricer@protonmail.com> 1635896518 -0500 commit: add api package

@ -0,0 +1 @@
0000000000000000000000000000000000000000 1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 Zach Rice <zricer@protonmail.com> 1635896329 -0500 clone: from github.com:gitleaks/test.git

@ -0,0 +1 @@
0000000000000000000000000000000000000000 a122b33c6bad3ee54724f52f2caad385ab1982ab Zach Rice <zricer@protonmail.com> 1635896552 -0500 update by push

@ -0,0 +1 @@
0000000000000000000000000000000000000000 f1b58b97808f8e744f6a23c693859df5b5968901 Zach Rice <zricer@protonmail.com> 1635896935 -0500 update by push

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save