Lint / golangci-lint (push) Waiting to run
Lint / semgrep (push) Waiting to run
Scan for secrets / test (push) Waiting to run
Test / test (push) Waiting to run
Test / test-community (push) Waiting to run
Release / mark-latest (push) Canceled after 0s
Release / Release (push) Canceled after 0s
We want to move the detector types out of the Scanning team purview. So I split off detector types into its own proto file (so that file detector_type.proto can be owned by the Integrations team), regenerated the pb files with "make protos", and made the detector files use the new generated detector_type.pb.go. Included the new detector_type.proto file in CODEOWNERS and made CODEOWNERS categories that contain larger teams be towards the top so that more fine grained ownership is filtered properly.
166 lines
7.8 KiB
Go
166 lines
7.8 KiB
Go
package flyio
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/google/go-cmp/cmp"
|
|
|
|
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors"
|
|
"github.com/trufflesecurity/trufflehog/v3/pkg/engine/ahocorasick"
|
|
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/detector_typepb"
|
|
)
|
|
|
|
func TestFlyio_Pattern(t *testing.T) {
|
|
d := Scanner{}
|
|
ahoCorasickCore := ahocorasick.NewAhoCorasickCore([]detectors.Detector{d})
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
want []string
|
|
}{
|
|
{
|
|
name: "typical pattern",
|
|
input: "flyio_token = 'FlyV1 fm2_AD1shwGbLSpZSPEXM1vhcbPZowurCDkXySOOJj0w4G2abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'",
|
|
want: []string{"FlyV1 fm2_AD1shwGbLSpZSPEXM1vhcbPZowurCDkXySOOJj0w4G2abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"},
|
|
},
|
|
{
|
|
name: "invalid pattern - too short",
|
|
input: "flyio_token = 'FlyV1 fm2_short'",
|
|
want: []string{},
|
|
},
|
|
{
|
|
name: "invalid pattern - wrong prefix",
|
|
input: "flyio_token = 'FlyV2 fm2_AD1shwGbLSpZSPEXM1vhcbPZowurCDkXySOOJj0w4G2abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'",
|
|
want: []string{},
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
matchedDetectors := ahoCorasickCore.FindDetectorMatches([]byte(test.input))
|
|
if len(test.want) > 0 && len(matchedDetectors) == 0 {
|
|
t.Errorf("keywords '%v' not matched by: %s", d.Keywords(), test.input)
|
|
return
|
|
}
|
|
|
|
results, err := d.FromData(context.Background(), false, []byte(test.input))
|
|
if err != nil {
|
|
t.Errorf("error = %v", err)
|
|
return
|
|
}
|
|
|
|
if len(results) != len(test.want) {
|
|
if len(results) == 0 && len(test.want) > 0 {
|
|
t.Errorf("did not receive result")
|
|
} else if len(results) > 0 && len(test.want) == 0 {
|
|
t.Errorf("expected no results, but received %d", len(results))
|
|
} else {
|
|
t.Errorf("expected %d results, only received %d", len(test.want), len(results))
|
|
}
|
|
return
|
|
}
|
|
|
|
actual := make(map[string]struct{}, len(results))
|
|
for _, r := range results {
|
|
if len(r.RawV2) > 0 {
|
|
actual[string(r.RawV2)] = struct{}{}
|
|
} else {
|
|
actual[string(r.Raw)] = struct{}{}
|
|
}
|
|
}
|
|
expected := make(map[string]struct{}, len(test.want))
|
|
for _, v := range test.want {
|
|
expected[v] = struct{}{}
|
|
}
|
|
|
|
if diff := cmp.Diff(expected, actual); diff != "" {
|
|
t.Errorf("%s diff: (-want +got)\n%s", test.name, diff)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestFlyio_IsFalsePositive(t *testing.T) {
|
|
s := Scanner{}
|
|
|
|
tests := []struct {
|
|
name string
|
|
token string
|
|
expected bool
|
|
reason string
|
|
}{
|
|
{
|
|
name: "token with AAAAAA - should not be flagged as false positive",
|
|
token: "FlyV1 fm2_abcdAAAAAA1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890",
|
|
expected: false,
|
|
reason: "",
|
|
},
|
|
{
|
|
name: "token with example pattern - should be false positive",
|
|
token: "FlyV1 fm2_1234example567890zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA0987654321zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA0987654321zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA0987654321zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA0987654321zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA0987654321zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA0987654321zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA0987654321zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA0987654321zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA0987654321",
|
|
expected: true,
|
|
reason: "contains term: example",
|
|
},
|
|
{
|
|
name: "token with sample pattern - should be false positive",
|
|
token: "FlyV1 fm2_1234sample567890zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA0987654321zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA0987654321zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA0987654321zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA0987654321zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA0987654321zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA0987654321zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA0987654321zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA0987654321zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA0987654321",
|
|
expected: true,
|
|
reason: "contains term: sample",
|
|
},
|
|
{
|
|
name: "token with xxxxxx pattern - should be false positive",
|
|
token: "FlyV1 fm2_1234xxxxxx567890zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA0987654321zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA0987654321zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA0987654321zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA0987654321zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA0987654321zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA0987654321zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA0987654321zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA0987654321zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA0987654321",
|
|
expected: true,
|
|
reason: "contains term: xxxxxx",
|
|
},
|
|
{
|
|
name: "valid token without AAAAAA - should not be false positive",
|
|
token: "FlyV1 fm2_1234567890zyxwvutsrqponmlkjihgfZYXWVUTSRQPONMLKJIHGF0987654321zyxwvutsrqponmlkjihgfZYXWVUTSRQPONMLKJIHGF0987654321zyxwvutsrqponmlkjihgfZYXWVUTSRQPONMLKJIHGF0987654321zyxwvutsrqponmlkjihgfZYXWVUTSRQPONMLKJIHGF0987654321zyxwvutsrqponmlkjihgfZYXWVUTSRQPONMLKJIHGF0987654321zyxwvutsrqponmlkjihgfZYXWVUTSRQPONMLKJIHGF0987654321zyxwvutsrqponmlkjihgfZYXWVUTSRQPONMLKJIHGF0987654321zyxwvutsrqponmlkjihgfZYXWVUTSRQPONMLKJIHGF0987654321zyxwvutsrqponmlkjihgfZYXWVUTSRQPONMLKJIHGF0987654321",
|
|
expected: false,
|
|
reason: "",
|
|
},
|
|
{
|
|
name: "regular string without pattern - should not be false positive",
|
|
token: "XYZABC123789def456",
|
|
expected: false,
|
|
reason: "",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
result := detectors.Result{
|
|
DetectorType: detector_typepb.DetectorType_FlyIO,
|
|
Raw: []byte(tt.token),
|
|
}
|
|
|
|
isFP, reason := s.IsFalsePositive(result)
|
|
|
|
if isFP != tt.expected {
|
|
t.Errorf("IsFalsePositive() got = %v, want %v (reason: %s)", isFP, tt.expected, reason)
|
|
}
|
|
|
|
if tt.expected && reason != tt.reason {
|
|
t.Errorf("IsFalsePositive() reason got = %v, want %v", reason, tt.reason)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func BenchmarkFromData(benchmark *testing.B) {
|
|
ctx := context.Background()
|
|
s := Scanner{}
|
|
for name, data := range detectors.MustGetBenchmarkData() {
|
|
benchmark.Run(name, func(b *testing.B) {
|
|
b.ResetTimer()
|
|
for n := 0; n < b.N; n++ {
|
|
_, err := s.FromData(ctx, false, data)
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|