Skip to content

Commit ad50575

Browse files
authored
Add commits and commits-file option (gitleaks#433)
1 parent 21d8187 commit ad50575

7 files changed

+154
-32
lines changed

options/options.go

+34-29
Original file line numberDiff line numberDiff line change
@@ -28,35 +28,40 @@ const (
2828

2929
// Options stores values of command line options
3030
type Options struct {
31-
Verbose bool `short:"v" long:"verbose" description:"Show verbose output from scan"`
32-
Repo string `short:"r" long:"repo" description:"Target repository"`
33-
Config string `long:"config" description:"config path"`
34-
Disk bool `long:"disk" description:"Clones repo(s) to disk"`
35-
Version bool `long:"version" description:"version number"`
36-
Username string `long:"username" description:"Username for git repo"`
37-
Password string `long:"password" description:"Password for git repo"`
38-
AccessToken string `long:"access-token" description:"Access token for git repo"`
39-
Commit string `long:"commit" description:"sha of commit to scan or \"latest\" to scan the last commit of the repository"`
40-
FilesAtCommit string `long:"files-at-commit" description:"sha of commit to scan all files at commit"`
41-
Threads int `long:"threads" description:"Maximum number of threads gitleaks spawns"`
42-
SSH string `long:"ssh-key" description:"path to ssh key used for auth"`
43-
Uncommited bool `long:"uncommitted" description:"run gitleaks on uncommitted code"`
44-
RepoPath string `long:"repo-path" description:"Path to repo"`
45-
OwnerPath string `long:"owner-path" description:"Path to owner directory (repos discovered)"`
46-
Branch string `long:"branch" description:"Branch to scan"`
47-
Report string `long:"report" description:"path to write json leaks file"`
48-
ReportFormat string `long:"report-format" default:"json" description:"json, csv, sarif"`
49-
Redact bool `long:"redact" description:"redact secrets from log messages and leaks"`
50-
Debug bool `long:"debug" description:"log debug messages"`
51-
RepoConfig bool `long:"repo-config" description:"Load config from target repo. Config file must be \".gitleaks.toml\" or \"gitleaks.toml\""`
52-
PrettyPrint bool `long:"pretty" description:"Pretty print json if leaks are present"`
53-
CommitFrom string `long:"commit-from" description:"Commit to start scan from"`
54-
CommitTo string `long:"commit-to" description:"Commit to stop scan"`
55-
CommitSince string `long:"commit-since" description:"Scan commits more recent than a specific date. Ex: '2006-01-02' or '2006-01-02T15:04:05-0700' format."`
56-
CommitUntil string `long:"commit-until" description:"Scan commits older than a specific date. Ex: '2006-01-02' or '2006-01-02T15:04:05-0700' format."`
57-
Timeout string `long:"timeout" description:"Time allowed per scan. Ex: 10us, 30s, 1m, 1h10m1s"`
58-
Depth int `long:"depth" description:"Number of commits to scan"`
59-
Deletion bool `long:"include-deletion" description:"Scan for patch deletions in addition to patch additions"`
31+
Verbose bool `short:"v" long:"verbose" description:"Show verbose output from scan"`
32+
Repo string `short:"r" long:"repo" description:"Target repository"`
33+
Config string `long:"config" description:"config path"`
34+
Disk bool `long:"disk" description:"Clones repo(s) to disk"`
35+
Version bool `long:"version" description:"version number"`
36+
Username string `long:"username" description:"Username for git repo"`
37+
Password string `long:"password" description:"Password for git repo"`
38+
AccessToken string `long:"access-token" description:"Access token for git repo"`
39+
FilesAtCommit string `long:"files-at-commit" description:"sha of commit to scan all files at commit"`
40+
Threads int `long:"threads" description:"Maximum number of threads gitleaks spawns"`
41+
SSH string `long:"ssh-key" description:"path to ssh key used for auth"`
42+
Uncommited bool `long:"uncommitted" description:"run gitleaks on uncommitted code"`
43+
RepoPath string `long:"repo-path" description:"Path to repo"`
44+
OwnerPath string `long:"owner-path" description:"Path to owner directory (repos discovered)"`
45+
Branch string `long:"branch" description:"Branch to scan"`
46+
Report string `long:"report" description:"path to write json leaks file"`
47+
ReportFormat string `long:"report-format" default:"json" description:"json, csv, sarif"`
48+
Redact bool `long:"redact" description:"redact secrets from log messages and leaks"`
49+
Debug bool `long:"debug" description:"log debug messages"`
50+
RepoConfig bool `long:"repo-config" description:"Load config from target repo. Config file must be \".gitleaks.toml\" or \"gitleaks.toml\""`
51+
PrettyPrint bool `long:"pretty" description:"Pretty print json if leaks are present"`
52+
53+
// Commit Options
54+
Commit string `long:"commit" description:"sha of commit to scan or \"latest\" to scan the last commit of the repository"`
55+
Commits string `long:"commits" description:"comma separated list of a commits to scan"`
56+
CommitsFile string `long:"commits-file" description:"file of new line separated list of a commits to scan"`
57+
CommitFrom string `long:"commit-from" description:"Commit to start scan from"`
58+
CommitTo string `long:"commit-to" description:"Commit to stop scan"`
59+
CommitSince string `long:"commit-since" description:"Scan commits more recent than a specific date. Ex: '2006-01-02' or '2006-01-02T15:04:05-0700' format."`
60+
CommitUntil string `long:"commit-until" description:"Scan commits older than a specific date. Ex: '2006-01-02' or '2006-01-02T15:04:05-0700' format."`
61+
62+
Timeout string `long:"timeout" description:"Time allowed per scan. Ex: 10us, 30s, 1m, 1h10m1s"`
63+
Depth int `long:"depth" description:"Number of commits to scan"`
64+
Deletion bool `long:"include-deletion" description:"Scan for patch deletions in addition to patch additions"`
6065

6166
// Hosts
6267
Host string `long:"host" description:"git hosting service like gitlab or github. Supported hosts include: Github, Gitlab"`

scan/scan.go

+29-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
package scan
22

33
import (
4+
"bufio"
45
"bytes"
56
"fmt"
67
"io"
8+
"os"
9+
"strings"
710
"sync"
811
"time"
912

@@ -71,11 +74,36 @@ func (repo *Repo) Scan() error {
7174

7275
scanTimeStart := time.Now()
7376

74-
// scan Commit patches OR all files at Commit. See https://github.com/zricethezav/gitleaks/issues/326
77+
// See https://github.com/zricethezav/gitleaks/issues/326
78+
// Scan commit patches, all files at a commit, or a range of commits
7579
if repo.Manager.Opts.Commit != "" {
7680
return scanCommit(repo.Manager.Opts.Commit, repo, scanCommitPatches)
7781
} else if repo.Manager.Opts.FilesAtCommit != "" {
7882
return scanCommit(repo.Manager.Opts.FilesAtCommit, repo, scanFilesAtCommit)
83+
} else if repo.Manager.Opts.Commits != "" {
84+
commits := strings.Split(repo.Manager.Opts.Commits, ",")
85+
for _, c := range commits {
86+
err := scanCommit(c, repo, scanCommitPatches)
87+
if err != nil {
88+
return err
89+
}
90+
}
91+
return nil
92+
} else if repo.Manager.Opts.CommitsFile != "" {
93+
file, err := os.Open(repo.Manager.Opts.CommitsFile)
94+
if err != nil {
95+
return err
96+
}
97+
defer file.Close()
98+
99+
scanner := bufio.NewScanner(file)
100+
for scanner.Scan() {
101+
err := scanCommit(scanner.Text(), repo, scanCommitPatches)
102+
if err != nil {
103+
return err
104+
}
105+
}
106+
return nil
79107
}
80108

81109
logOpts, err := getLogOptions(repo)

scan/scan_test.go

+22-2
Original file line numberDiff line numberDiff line change
@@ -96,16 +96,36 @@ func TestScan(t *testing.T) {
9696
wantPath: "../test_data/test_local_repo_two_leaks_commit_to.json",
9797
},
9898
{
99-
description: "test local repo two leaks range Commit",
99+
description: "test local repo two leaks to from Commit",
100100
opts: options.Options{
101101
RepoPath: "../test_data/test_repos/test_repo_2",
102-
Report: "../test_data/test_local_repo_two_leaks_commit_range.json.got",
102+
Report: "../test_data/test_local_repo_two_leaks_commit_to_from.json.got",
103103
ReportFormat: "json",
104104
CommitFrom: "d8ac0b73aeeb45843319cdc5ce506516eb49bf7a",
105105
CommitTo: "51f6dcf6b89b93f4075ba92c400b075631a6cc93",
106106
},
107+
wantPath: "../test_data/test_local_repo_two_leaks_commit_to_from.json",
108+
},
109+
{
110+
description: "test local repo two leaks list Commits",
111+
opts: options.Options{
112+
RepoPath: "../test_data/test_repos/test_repo_2",
113+
Report: "../test_data/test_local_repo_two_leaks_commit_range.json.got",
114+
ReportFormat: "json",
115+
Commits: "d8ac0b73aeeb45843319cdc5ce506516eb49bf7a,996865bb912f3bc45898a370a13aadb315014b55,17471a5fda722a9e423f1a0d3f0d267ea009d41c,51f6dcf6b89b93f4075ba92c400b075631a6cc93,b10b3e2cb320a8c211fda94c4567299d37de7776",
116+
},
107117
wantPath: "../test_data/test_local_repo_two_leaks_commit_range.json",
108118
},
119+
{
120+
description: "test local repo two leaks file list commits",
121+
opts: options.Options{
122+
RepoPath: "../test_data/test_repos/test_repo_2",
123+
Report: "../test_data/test_local_repo_two_leaks_file_commit_range.json.got",
124+
ReportFormat: "json",
125+
CommitsFile: "../test_data/test_options/test_local_repo_commits.txt",
126+
},
127+
wantPath: "../test_data/test_local_repo_two_leaks_file_commit_range.json",
128+
},
109129
{
110130
description: "test local repo two leaks globally allowlisted",
111131
opts: options.Options{

test_data/test_local_repo_two_leaks_commit_range.json

+15
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,20 @@
1313
"date": "2019-10-25T13:01:27-04:00",
1414
"tags": "key, AWS",
1515
"operation": "addition"
16+
},
17+
{
18+
"line": "Here's an AWS secret: AKIALALEMEL33243OLIAE",
19+
"lineNumber": 3,
20+
"offender": "AKIALALEMEL33243OLIA",
21+
"commit": "b10b3e2cb320a8c211fda94c4567299d37de7776",
22+
"repo": "test_repo_2",
23+
"rule": "AWS Manager ID",
24+
"commitMessage": "adding aws key\n",
25+
"author": "zach rice",
26+
"email": "[email protected]",
27+
"file": "secrets.md",
28+
"date": "2019-10-25T12:58:39-04:00",
29+
"tags": "key, AWS",
30+
"operation": "addition"
1631
}
1732
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[
2+
{
3+
"line": "Here's an AWS secret: \"AKIALALEMEL33243OLIAE\"",
4+
"lineNumber": 5,
5+
"offender": "AKIALALEMEL33243OLIA",
6+
"commit": "17471a5fda722a9e423f1a0d3f0d267ea009d41c",
7+
"repo": "test_repo_2",
8+
"rule": "AWS Manager ID",
9+
"commitMessage": "wait this is actually adding an aws secret\n",
10+
"author": "zach rice",
11+
"email": "[email protected]",
12+
"file": "secrets.md",
13+
"date": "2019-10-25T13:01:27-04:00",
14+
"tags": "key, AWS",
15+
"operation": "addition"
16+
}
17+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
[
2+
{
3+
"line": "Here's an AWS secret: \"AKIALALEMEL33243OLIAE\"",
4+
"lineNumber": 5,
5+
"offender": "AKIALALEMEL33243OLIA",
6+
"commit": "17471a5fda722a9e423f1a0d3f0d267ea009d41c",
7+
"repo": "test_repo_2",
8+
"rule": "AWS Manager ID",
9+
"commitMessage": "wait this is actually adding an aws secret\n",
10+
"author": "zach rice",
11+
"email": "[email protected]",
12+
"file": "secrets.md",
13+
"date": "2019-10-25T13:01:27-04:00",
14+
"tags": "key, AWS",
15+
"operation": "addition"
16+
},
17+
{
18+
"line": "Here's an AWS secret: AKIALALEMEL33243OLIAE",
19+
"lineNumber": 3,
20+
"offender": "AKIALALEMEL33243OLIA",
21+
"commit": "b10b3e2cb320a8c211fda94c4567299d37de7776",
22+
"repo": "test_repo_2",
23+
"rule": "AWS Manager ID",
24+
"commitMessage": "adding aws key\n",
25+
"author": "zach rice",
26+
"email": "[email protected]",
27+
"file": "secrets.md",
28+
"date": "2019-10-25T12:58:39-04:00",
29+
"tags": "key, AWS",
30+
"operation": "addition"
31+
}
32+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
d8ac0b73aeeb45843319cdc5ce506516eb49bf7a
2+
996865bb912f3bc45898a370a13aadb315014b55
3+
17471a5fda722a9e423f1a0d3f0d267ea009d41c
4+
51f6dcf6b89b93f4075ba92c400b075631a6cc93
5+
b10b3e2cb320a8c211fda94c4567299d37de7776

0 commit comments

Comments
 (0)