Skip to content

Commit 9d496a6

Browse files
authored
Merge pull request #87 from CompassSecurity/71-allow-disabling-trufflehog-verification
allow disabling the trufflehog verification
2 parents 3d22395 + f37cd96 commit 9d496a6

File tree

4 files changed

+42
-29
lines changed

4 files changed

+42
-29
lines changed

src/pipeleak/cmd/scan.go

+1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ func NewScanCmd() *cobra.Command {
4848
scanCmd.PersistentFlags().StringVarP(&maxArtifactSize, "max-artifact-size", "", "500Mb", "Max file size of an artifact to be included in scanning. Larger files are skipped. Format: https://pkg.go.dev/github.com/docker/go-units#FromHumanSize")
4949
scanCmd.PersistentFlags().IntVarP(&options.MaxScanGoRoutines, "threads", "", 4, "Nr of threads used to scan")
5050
scanCmd.PersistentFlags().StringVarP(&options.QueueFolder, "queue", "q", "", "Relative folderpath where the queue files will be stored. Defaults to system tmp")
51+
scanCmd.PersistentFlags().BoolVarP(&options.TruffleHogVerification, "truffleHogVerification", "", true, "Enable the TruffleHog credential verification, will actively test the found credentials and only report those. Disable with --truffleHogVerification=false")
5152

5253
scanCmd.PersistentFlags().BoolVarP(&options.Verbose, "verbose", "v", false, "Verbose logging")
5354

src/pipeleak/scanner/pipeline.go

+17-13
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,20 @@ var queueFileName string
2424
var queueDB *sql.DB
2525

2626
type ScanOptions struct {
27-
GitlabUrl string
28-
GitlabApiToken string
29-
GitlabCookie string
30-
ProjectSearchQuery string
31-
Artifacts bool
32-
Owned bool
33-
Member bool
34-
JobLimit int
35-
Verbose bool
36-
ConfidenceFilter []string
37-
MaxArtifactSize int64
38-
MaxScanGoRoutines int
39-
QueueFolder string
27+
GitlabUrl string
28+
GitlabApiToken string
29+
GitlabCookie string
30+
ProjectSearchQuery string
31+
Artifacts bool
32+
Owned bool
33+
Member bool
34+
JobLimit int
35+
Verbose bool
36+
ConfidenceFilter []string
37+
MaxArtifactSize int64
38+
MaxScanGoRoutines int
39+
QueueFolder string
40+
TruffleHogVerification bool
4041
}
4142

4243
func ScanGitLabPipelines(options *ScanOptions) {
@@ -50,6 +51,9 @@ func ScanGitLabPipelines(options *ScanOptions) {
5051
})
5152

5253
InitRules(options.ConfidenceFilter)
54+
if !options.TruffleHogVerification {
55+
log.Info().Msg("TruffleHog verification is disabled")
56+
}
5357

5458
git, err := helper.GetGitlabClient(options.GitlabApiToken, options.GitlabUrl)
5559
if err != nil {

src/pipeleak/scanner/queue.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ func analyzeJobTrace(git *gitlab.Client, item QueueItem, options *ScanOptions) {
102102
return
103103
}
104104

105-
findings := DetectHits(trace, options.MaxScanGoRoutines)
105+
findings := DetectHits(trace, options.MaxScanGoRoutines, options.TruffleHogVerification)
106106
for _, finding := range findings {
107107
log.Warn().Str("confidence", finding.Pattern.Pattern.Confidence).Str("ruleName", finding.Pattern.Pattern.Name).Str("value", finding.Text).Str("url", item.Meta.JobWebUrl).Str("jobName", item.Meta.JobName).Msg("HIT")
108108
}
@@ -140,9 +140,9 @@ func analyzeJobArtifact(git *gitlab.Client, item QueueItem, options *ScanOptions
140140
kind, _ := filetype.Match(content)
141141
// do not scan https://pkg.go.dev/github.com/h2non/filetype#readme-supported-types
142142
if kind == filetype.Unknown {
143-
DetectFileHits(content, item.Meta.JobWebUrl, item.Meta.JobName, file.Name, "")
143+
DetectFileHits(content, item.Meta.JobWebUrl, item.Meta.JobName, file.Name, "", options.TruffleHogVerification)
144144
} else if filetype.IsArchive(content) {
145-
handleArchiveArtifact(file.Name, content, item.Meta.JobWebUrl, item.Meta.JobName)
145+
handleArchiveArtifact(file.Name, content, item.Meta.JobWebUrl, item.Meta.JobName, options.TruffleHogVerification)
146146
}
147147
fc.Close()
148148
})
@@ -157,7 +157,7 @@ func analyzeDotenvArtifact(git *gitlab.Client, item QueueItem, options *ScanOpti
157157
return
158158
}
159159

160-
findings := DetectHits(dotenvText, options.MaxScanGoRoutines)
160+
findings := DetectHits(dotenvText, options.MaxScanGoRoutines, options.TruffleHogVerification)
161161
for _, finding := range findings {
162162
artifactsBaseUrl, _ := url.JoinPath(item.Meta.JobWebUrl, "/-/artifacts")
163163
log.Warn().Str("confidence", finding.Pattern.Pattern.Confidence).Str("ruleName", finding.Pattern.Pattern.Name).Str("value", finding.Text).Str("artifactUrl", artifactsBaseUrl).Int("jobId", item.Meta.JobId).Str("jobName", item.Meta.JobName).Msg("HIT DOTENV: Check artifacts page which is the only place to download the dotenv file")
@@ -286,7 +286,7 @@ func DownloadEnvArtifact(cookieVal string, gitlabUrl string, prjectPath string,
286286
// https://docs.gitlab.com/ee/ci/caching/#common-use-cases-for-caches
287287
var skippableDirectoryNames = []string{"node_modules", ".yarn", ".yarn-cache", ".npm", "venv", "vendor", ".go/pkg/mod/"}
288288

289-
func handleArchiveArtifact(archivefileName string, content []byte, jobWebUrl string, jobName string) {
289+
func handleArchiveArtifact(archivefileName string, content []byte, jobWebUrl string, jobName string, enableTruffleHogVerification bool) {
290290
for _, skipKeyword := range skippableDirectoryNames {
291291
if strings.Contains(archivefileName, skipKeyword) {
292292
log.Debug().Str("file", archivefileName).Str("keyword", skipKeyword).Msg("Skipped archive due to blocklist entry")
@@ -342,7 +342,7 @@ func handleArchiveArtifact(archivefileName string, content []byte, jobWebUrl str
342342

343343
kind, _ := filetype.Match(fileBytes)
344344
if kind == filetype.Unknown {
345-
DetectFileHits(fileBytes, jobWebUrl, jobName, path.Base(fPath), archivefileName)
345+
DetectFileHits(fileBytes, jobWebUrl, jobName, path.Base(fPath), archivefileName, enableTruffleHogVerification)
346346
}
347347
}
348348
}

src/pipeleak/scanner/rules.go

+18-10
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ func AppendPipeleakRules(rules []PatternElement) []PatternElement {
141141
return slices.Concat(rules, customRules)
142142
}
143143

144-
func DetectHits(text []byte, maxThreads int) []Finding {
144+
func DetectHits(text []byte, maxThreads int, enableTruffleHogVerification bool) []Finding {
145145
ctx := context.Background()
146146
group := parallel.Collect[[]Finding](parallel.Limited(ctx, maxThreads))
147147

@@ -179,21 +179,29 @@ func DetectHits(text []byte, maxThreads int) []Finding {
179179
for _, detector := range defaults.DefaultDetectors() {
180180
trGroup.Go(func(ctx context.Context) ([]Finding, error) {
181181
findingsTr := []Finding{}
182-
trHits, err := detector.FromData(ctx, true, text)
182+
trHits, err := detector.FromData(ctx, enableTruffleHogVerification, text)
183183
if err != nil {
184184
log.Error().Msg("Truffelhog Detector Failed " + err.Error())
185185
return []Finding{}, err
186186
}
187187

188188
for _, result := range trHits {
189-
// only report verified
189+
secret := result.Raw
190+
if len(result.RawV2) > 0 {
191+
secret = result.RawV2
192+
}
193+
finding := Finding{Pattern: PatternElement{Pattern: PatternPattern{Name: result.DetectorType.String(), Confidence: "high-verified"}}, Text: string(secret)}
194+
195+
// if trufflehog verification is enalbed ONLY verified rules are reported
190196
if result.Verified {
191-
secret := result.Raw
192-
if len(result.RawV2) > 0 {
193-
secret = result.Raw
194-
}
197+
findingsTr = append(findingsTr, finding)
198+
}
195199

196-
findingsTr = append(findingsTr, Finding{Pattern: PatternElement{Pattern: PatternPattern{Name: result.DetectorType.String(), Confidence: "high-verified"}}, Text: string(secret)})
200+
// if trufflehog verification is disabled all rules are reported
201+
if !enableTruffleHogVerification {
202+
// trufflehog itself does not have confidence information
203+
finding.Pattern.Pattern.Confidence = "trufflehog-unverified"
204+
findingsTr = append(findingsTr, finding)
197205
}
198206
}
199207
return findingsTr, nil
@@ -231,9 +239,9 @@ func deduplicateFindings(totalFindings []Finding) []Finding {
231239
return dedupedFindings
232240
}
233241

234-
func DetectFileHits(content []byte, jobWebUrl string, jobName string, fileName string, archiveName string) {
242+
func DetectFileHits(content []byte, jobWebUrl string, jobName string, fileName string, archiveName string, enableTruffleHogVerification bool) {
235243
// 1 goroutine to prevent maxThreads^2 which trashes memory
236-
findings := DetectHits(content, 1)
244+
findings := DetectHits(content, 1, enableTruffleHogVerification)
237245
for _, finding := range findings {
238246
baseLog := log.Warn().Str("confidence", finding.Pattern.Pattern.Confidence).Str("ruleName", finding.Pattern.Pattern.Name).Str("value", finding.Text).Str("url", jobWebUrl).Str("jobName", jobName).Str("file", fileName)
239247
if len(archiveName) > 0 {

0 commit comments

Comments
 (0)