feat(detectors): use map for false positives

This commit is contained in:
Richard Gomez 2024-06-16 15:39:28 -04:00 committed by Richard Gomez
parent 5ecc35cdd2
commit 4e6d5a1ccc
4 changed files with 25 additions and 13 deletions

View file

@ -14,8 +14,10 @@ import (
) )
var ( var (
DefaultFalsePositives = []FalsePositive{"example", "xxxxxx", "aaaaaa", "abcde", "00000", "sample", "*****"} DefaultFalsePositives = map[FalsePositive]struct{}{
UuidFalsePositives []FalsePositive "example": {}, "xxxxxx": {}, "aaaaaa": {}, "abcde": {}, "00000": {}, "sample": {}, "*****": {},
}
UuidFalsePositives map[FalsePositive]struct{}
) )
type FalsePositive string type FalsePositive string
@ -59,9 +61,9 @@ func init() {
filter = builder.Build() filter = builder.Build()
// Populate custom FalsePositive list // Populate custom FalsePositive list
UuidFalsePositives = make([]FalsePositive, len(uuidList)) UuidFalsePositives = make(map[FalsePositive]struct{}, len(uuidList))
for i, uuid := range uuidList { for _, uuid := range uuidList {
UuidFalsePositives[i] = FalsePositive(uuid) UuidFalsePositives[FalsePositive(uuid)] = struct{}{}
} }
} }
@ -80,16 +82,19 @@ func GetFalsePositiveCheck(detector Detector) func(Result) (bool, string) {
// //
// Currently, this includes: english word in key or matches common example patterns. // Currently, this includes: english word in key or matches common example patterns.
// Only the secret key material should be passed into this function // Only the secret key material should be passed into this function
func IsKnownFalsePositive(match string, falsePositives []FalsePositive, wordCheck bool) (bool, string) { func IsKnownFalsePositive(match string, falsePositives map[FalsePositive]struct{}, wordCheck bool) (bool, string) {
if !utf8.ValidString(match) { if !utf8.ValidString(match) {
return true, "invalid utf8" return true, "invalid utf8"
} }
lower := strings.ToLower(match) lower := strings.ToLower(match)
for _, fp := range falsePositives { for fp := range falsePositives {
fps := string(fp) fps := string(fp)
if strings.Contains(lower, fps) { if lower == fps {
return true, "matches term: " + fps return true, "matches term: " + fps
} }
if strings.Contains(lower, fps) {
return true, "contains term: " + fps
}
} }
if wordCheck { if wordCheck {

View file

@ -27,7 +27,7 @@ func (d fakeDetector) Type() detectorspb.DetectorType {
} }
func (d customFalsePositiveChecker) IsFalsePositive(result Result) (bool, string) { func (d customFalsePositiveChecker) IsFalsePositive(result Result) (bool, string) {
return IsKnownFalsePositive(string(result.Raw), []FalsePositive{"a specific magic string"}, false) return IsKnownFalsePositive(string(result.Raw), map[FalsePositive]struct{}{"a specific magic string": {}}, false)
} }
func TestFilterKnownFalsePositives_DefaultLogic(t *testing.T) { func TestFilterKnownFalsePositives_DefaultLogic(t *testing.T) {
@ -68,7 +68,7 @@ func TestFilterKnownFalsePositives_CustomLogic(t *testing.T) {
func TestIsFalsePositive(t *testing.T) { func TestIsFalsePositive(t *testing.T) {
type args struct { type args struct {
match string match string
falsePositives []FalsePositive falsePositives map[FalsePositive]struct{}
useWordlist bool useWordlist bool
} }
tests := []struct { tests := []struct {

View file

@ -103,8 +103,12 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
return results, nil return results, nil
} }
var ftpFalsePositives = map[detectors.FalsePositive]struct{}{
detectors.FalsePositive("@ftp.freebsd.org"): {},
}
func (s Scanner) IsFalsePositive(result detectors.Result) (bool, string) { func (s Scanner) IsFalsePositive(result detectors.Result) (bool, string) {
return detectors.IsKnownFalsePositive(string(result.Raw), []detectors.FalsePositive{"@ftp.freebsd.org"}, false) return detectors.IsKnownFalsePositive(string(result.Raw), ftpFalsePositives, false)
} }
func isErrDeterminate(e error) bool { func isErrDeterminate(e error) bool {

View file

@ -57,6 +57,10 @@ func (s Scanner) Keywords() []string {
return []string{"github", "gh", "pat", "token"} return []string{"github", "gh", "pat", "token"}
} }
var ghFalsePositives = map[detectors.FalsePositive]struct{}{
detectors.FalsePositive("github commit"): {},
}
// FromData will find and optionally verify GitHub secrets in a given set of bytes. // FromData will find and optionally verify GitHub secrets in a given set of bytes.
func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (results []detectors.Result, err error) { func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (results []detectors.Result, err error) {
dataStr := string(data) dataStr := string(data)
@ -73,8 +77,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
// Note that this false positive check happens **before** verification! I don't know why it's written this way // Note that this false positive check happens **before** verification! I don't know why it's written this way
// but that's why this logic wasn't moved into a CustomFalsePositiveChecker implementation. // but that's why this logic wasn't moved into a CustomFalsePositiveChecker implementation.
specificFPs := []detectors.FalsePositive{"github commit"} if isFp, _ := detectors.IsKnownFalsePositive(token, ghFalsePositives, false); isFp {
if isFp, _ := detectors.IsKnownFalsePositive(token, specificFPs, false); isFp {
continue continue
} }