Skip to content

Commit

Permalink
[thog-1548] add auto redaction for verification errors (#2106)
Browse files Browse the repository at this point in the history
* Updating VerificationError to have auto redaction logic
* find/replace error
  • Loading branch information
0x1 authored Dec 5, 2023
1 parent 692582f commit 11394ea
Show file tree
Hide file tree
Showing 163 changed files with 720 additions and 595 deletions.
2 changes: 1 addition & 1 deletion pkg/detectors/airtableapikey/airtableapikey_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ func TestAirtableApiKey_FromChunk(t *testing.T) {
}
got[i].Raw = nil
}
ignoreOpts := cmpopts.IgnoreFields(detectors.Result{}, "Raw", "RawV2", "VerificationError")
ignoreOpts := cmpopts.IgnoreFields(detectors.Result{}, "Raw", "RawV2", "verificationError")
if diff := cmp.Diff(got, tt.want, ignoreOpts); diff != "" {
t.Errorf("Airtable.FromData() %s diff: (-got +want)\n%s", tt.name, diff)
}
Expand Down
5 changes: 3 additions & 2 deletions pkg/detectors/alchemy/alchemy.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,11 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
} else if res.StatusCode == 401 {
// The secret is determinately not verified (nothing to do)
} else {
s1.VerificationError = fmt.Errorf("unexpected HTTP response status %d", res.StatusCode)
err = fmt.Errorf("unexpected HTTP response status %d", res.StatusCode)
s1.SetVerificationError(err, resMatch)
}
} else {
s1.VerificationError = err
s1.SetVerificationError(err, resMatch)
}
}

Expand Down
11 changes: 6 additions & 5 deletions pkg/detectors/alchemy/alchemy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ package alchemy
import (
"context"
"fmt"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"testing"
"time"

"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"

"github.com/trufflesecurity/trufflehog/v3/pkg/detectors"

"github.com/trufflesecurity/trufflehog/v3/pkg/common"
Expand Down Expand Up @@ -132,11 +133,11 @@ func TestAlchemy_FromChunk(t *testing.T) {
if len(got[i].Raw) == 0 {
t.Fatalf("no raw secret present: \n %+v", got[i])
}
if (got[i].VerificationError != nil) != tt.wantVerificationErr {
t.Fatalf("wantVerificationError = %v, verification error = %v", tt.wantVerificationErr, got[i].VerificationError)
if (got[i].VerificationError() != nil) != tt.wantVerificationErr {
t.Fatalf("wantVerificationError = %v, verification error = %v", tt.wantVerificationErr, got[i].VerificationError())
}
}
ignoreOpts := cmpopts.IgnoreFields(detectors.Result{}, "Raw", "VerificationError")
ignoreOpts := cmpopts.IgnoreFields(detectors.Result{}, "Raw", "verificationError")
if diff := cmp.Diff(got, tt.want, ignoreOpts); diff != "" {
t.Errorf("Alchemy.FromData() %s diff: (-got +want)\n%s", tt.name, diff)
}
Expand Down
8 changes: 5 additions & 3 deletions pkg/detectors/anthropic/anthropic.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
if res.StatusCode == http.StatusBadRequest {
var resp response
if err = json.NewDecoder(res.Body).Decode(&resp); err != nil {
s1.VerificationError = fmt.Errorf("unexpected HTTP response body: %w", err)
err = fmt.Errorf("unexpected HTTP response body: %w", err)
s1.SetVerificationError(err, resMatch)
continue
}
if resp.Error.Message == "max_tokens_to_sample: field required" {
Expand All @@ -95,10 +96,11 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
// The secret is determinately not verified (nothing to do)
// Anthropic returns 401 on all requests not containing a valid x-api-key header
} else {
s1.VerificationError = fmt.Errorf("unexpected HTTP response status %d", res.StatusCode)
err = fmt.Errorf("unexpected HTTP response status %d", res.StatusCode)
s1.SetVerificationError(err, resMatch)
}
} else {
s1.VerificationError = err
s1.SetVerificationError(err, resMatch)
}
}

Expand Down
11 changes: 6 additions & 5 deletions pkg/detectors/anthropic/anthropic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ package anthropic
import (
"context"
"fmt"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"testing"
"time"

"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"

"github.com/trufflesecurity/trufflehog/v3/pkg/detectors"

"github.com/trufflesecurity/trufflehog/v3/pkg/common"
Expand Down Expand Up @@ -132,11 +133,11 @@ func TestAnthropic_FromChunk(t *testing.T) {
if len(got[i].Raw) == 0 {
t.Fatalf("no raw secret present: \n %+v", got[i])
}
if (got[i].VerificationError != nil) != tt.wantVerificationErr {
t.Fatalf("wantVerificationError = %v, verification error = %v", tt.wantVerificationErr, got[i].VerificationError)
if (got[i].VerificationError() != nil) != tt.wantVerificationErr {
t.Fatalf("wantVerificationError = %v, verification error = %v", tt.wantVerificationErr, got[i].VerificationError())
}
}
ignoreOpts := cmpopts.IgnoreFields(detectors.Result{}, "Raw", "VerificationError")
ignoreOpts := cmpopts.IgnoreFields(detectors.Result{}, "Raw", "verificationError")
if diff := cmp.Diff(got, tt.want, ignoreOpts); diff != "" {
t.Errorf("Anthropic.FromData() %s diff: (-got +want)\n%s", tt.name, diff)
}
Expand Down
5 changes: 3 additions & 2 deletions pkg/detectors/appoptics/appoptics.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,11 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
} else if res.StatusCode == 401 {
// The secret is determinately not verified (nothing to do)
} else {
s1.VerificationError = fmt.Errorf("unexpected HTTP response status %d", res.StatusCode)
err = fmt.Errorf("unexpected HTTP response status %d", res.StatusCode)
s1.SetVerificationError(err, resMatch)
}
} else {
s1.VerificationError = err
s1.SetVerificationError(err, resMatch)
}
}

Expand Down
8 changes: 4 additions & 4 deletions pkg/detectors/appoptics/appoptics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ func TestAppoptics_FromChunk(t *testing.T) {
want: nil,
wantErr: false,
wantVerificationErr: false,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand All @@ -99,11 +99,11 @@ func TestAppoptics_FromChunk(t *testing.T) {
if len(got[i].Raw) == 0 {
t.Fatalf("no raw secret present: \n %+v", got[i])
}
if (got[i].VerificationError != nil) != tt.wantVerificationErr {
t.Fatalf("wantVerificationError = %v, verification error = %v", tt.wantVerificationErr, got[i].VerificationError)
if (got[i].VerificationError() != nil) != tt.wantVerificationErr {
t.Fatalf("wantVerificationError = %v, verification error = %v", tt.wantVerificationErr, got[i].VerificationError())
}
}
ignoreOpts := cmpopts.IgnoreFields(detectors.Result{}, "Raw", "VerificationError")
ignoreOpts := cmpopts.IgnoreFields(detectors.Result{}, "Raw", "verificationError")
if diff := cmp.Diff(got, tt.want, ignoreOpts); diff != "" {
t.Errorf("Appoptics.FromData() %s diff: (-got +want)\n%s", tt.name, diff)
}
Expand Down
10 changes: 6 additions & 4 deletions pkg/detectors/aws/aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,8 @@ func (s scanner) FromData(ctx context.Context, verify bool, data []byte) (result
}

if verify {
verified, extraData, verificationErr := s.verifyMatch(ctx, resIDMatch, resSecretMatch, true)
s1.Verified = verified
isVerified, extraData, verificationErr := s.verifyMatch(ctx, resIDMatch, resSecretMatch, true)
s1.Verified = isVerified
// It'd be good to log when calculated account value does not match
// the account value from verification. Should only be edge cases at most.
// if extraData["account"] != s1.ExtraData["account"] && extraData["account"] != "" {//log here}
Expand All @@ -148,7 +148,9 @@ func (s scanner) FromData(ctx context.Context, verify bool, data []byte) (result
for k, v := range extraData {
s1.ExtraData[k] = v
}
s1.VerificationError = verificationErr
if verificationErr != nil {
s1.SetVerificationError(verificationErr, resSecretMatch)
}
}

if !s1.Verified {
Expand Down Expand Up @@ -286,7 +288,7 @@ func (s scanner) verifyMatch(ctx context.Context, resIDMatch, resSecretMatch str
if strings.EqualFold(body.Error.Code, "InvalidClientTokenId") {
return false, nil, nil
} else {
return false, nil, fmt.Errorf("request to %v returned status %d with an unexpected reason (%s: %s)", res.Request.URL, res.StatusCode, body.Error.Code, body.Error.Message)
return false, nil, fmt.Errorf("request returned status %d with an unexpected reason (%s: %s)", res.StatusCode, body.Error.Code, body.Error.Message)
}
} else {
return false, nil, fmt.Errorf("couldn't parse the sts response body (%v)", err)
Expand Down
6 changes: 3 additions & 3 deletions pkg/detectors/aws/aws_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -314,11 +314,11 @@ func TestAWS_FromChunk(t *testing.T) {
if len(got[i].Raw) == 0 {
t.Fatalf("no raw secret present: \n %+v", got[i])
}
if (got[i].VerificationError != nil) != tt.wantVerificationError {
t.Fatalf("wantVerificationError %v, verification error = %v", tt.wantVerificationError, got[i].VerificationError)
if (got[i].VerificationError() != nil) != tt.wantVerificationError {
t.Fatalf("wantVerificationError %v, verification error = %v", tt.wantVerificationError, got[i].VerificationError())
}
}
ignoreOpts := cmpopts.IgnoreFields(detectors.Result{}, "RawV2", "Raw", "VerificationError")
ignoreOpts := cmpopts.IgnoreFields(detectors.Result{}, "RawV2", "Raw", "verificationError")
if diff := cmp.Diff(got, tt.want, ignoreOpts); diff != "" {
t.Errorf("AWS.FromData() %s diff: (-got +want)\n%s", tt.name, diff)
}
Expand Down
6 changes: 3 additions & 3 deletions pkg/detectors/awssessionkeys/awssessionkey.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,12 +134,12 @@ func (s scanner) FromData(ctx context.Context, verify bool, data []byte) (result
}

if verify {
verified, extraData, verificationErr := s.verifyMatch(ctx, resIDMatch, resSecretMatch, resSessionMatch, true)
s1.Verified = verified
isVerified, extraData, verificationErr := s.verifyMatch(ctx, resIDMatch, resSecretMatch, resSessionMatch, true)
s1.Verified = isVerified
if extraData != nil {
s1.ExtraData = extraData
}
s1.VerificationError = verificationErr
s1.SetVerificationError(verificationErr, resSecretMatch)
}

if !s1.Verified {
Expand Down
6 changes: 3 additions & 3 deletions pkg/detectors/azurebatch/azurebatch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,11 @@ func TestAzurebatch_FromChunk(t *testing.T) {
if len(got[i].Raw) == 0 {
t.Fatalf("no raw secret present: \n %+v", got[i])
}
if (got[i].VerificationError != nil) != tt.wantVerificationErr {
t.Fatalf("wantVerificationError = %v, verification error = %v", tt.wantVerificationErr, got[i].VerificationError)
if (got[i].VerificationError() != nil) != tt.wantVerificationErr {
t.Fatalf("wantVerificationError = %v, verification error = %v", tt.wantVerificationErr, got[i].VerificationError())
}
}
ignoreOpts := cmpopts.IgnoreFields(detectors.Result{}, "RawV2", "Raw", "Redacted", "VerificationError")
ignoreOpts := cmpopts.IgnoreFields(detectors.Result{}, "RawV2", "Raw", "Redacted", "verificationError")

if diff := cmp.Diff(got, tt.want, ignoreOpts); diff != "" {
t.Errorf("AzureBatch.FromData() %s diff: (-got +want)\n%s", tt.name, diff)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,11 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
} else if res.StatusCode == 401 {
// The secret is determinately not verified (nothing to do)
} else {
s1.VerificationError = fmt.Errorf("unexpected HTTP response status %d", res.StatusCode)
err = fmt.Errorf("unexpected HTTP response status %d", res.StatusCode)
s1.SetVerificationError(err, password)
}
} else {
s1.VerificationError = err
s1.SetVerificationError(err, username, password)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ package azurecontainerregistry
import (
"context"
"fmt"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"testing"
"time"

"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"

"github.com/trufflesecurity/trufflehog/v3/pkg/detectors"

"github.com/trufflesecurity/trufflehog/v3/pkg/common"
Expand All @@ -28,7 +29,6 @@ func TestAzureContainerRegistry_FromChunk(t *testing.T) {
password := testSecrets.MustGetField("AZURE_CR_PASSWORD")
passwordInactive := testSecrets.MustGetField("AZURE_CR_PASSWORD_INACTIVE")


type args struct {
ctx context.Context
data []byte
Expand Down Expand Up @@ -100,11 +100,11 @@ func TestAzureContainerRegistry_FromChunk(t *testing.T) {
if len(got[i].Raw) == 0 {
t.Fatalf("no raw secret present: \n %+v", got[i])
}
if (got[i].VerificationError != nil) != tt.wantVerificationErr {
t.Fatalf("wantVerificationError = %v, verification error = %v", tt.wantVerificationErr, got[i].VerificationError)
if (got[i].VerificationError() != nil) != tt.wantVerificationErr {
t.Fatalf("wantVerificationError = %v, verification error = %v", tt.wantVerificationErr, got[i].VerificationError())
}
}
ignoreOpts := cmpopts.IgnoreFields(detectors.Result{}, "RawV2", "Raw","Redacted", "VerificationError")
ignoreOpts := cmpopts.IgnoreFields(detectors.Result{}, "RawV2", "Raw", "Redacted", "verificationError")
if diff := cmp.Diff(got, tt.want, ignoreOpts); diff != "" {
t.Errorf("AzureContainerRegistry.FromData() %s diff: (-got +want)\n%s", tt.name, diff)
}
Expand Down
5 changes: 3 additions & 2 deletions pkg/detectors/azurestorage/azurestorage.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,11 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
s1.Verified = true
} else if res.StatusCode == 403 {
} else {
s1.VerificationError = fmt.Errorf("unexpected HTTP response status %d", res.StatusCode)
err = fmt.Errorf("unexpected HTTP response status %d", res.StatusCode)
s1.SetVerificationError(err, accountKey)
}
} else {
s1.VerificationError = err
s1.SetVerificationError(err, accountKey)
}
}

Expand Down
6 changes: 3 additions & 3 deletions pkg/detectors/azurestorage/azurestorage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,11 +133,11 @@ func TestAzurestorage_FromChunk(t *testing.T) {
if len(got[i].Raw) == 0 {
t.Fatalf("no raw secret present: \n %+v", got[i])
}
if (got[i].VerificationError != nil) != tt.wantVerificationErr {
t.Fatalf("wantVerificationError = %v, verification error = %v", tt.wantVerificationErr, got[i].VerificationError)
if (got[i].VerificationError() != nil) != tt.wantVerificationErr {
t.Fatalf("wantVerificationError = %v, verification error = %v", tt.wantVerificationErr, got[i].VerificationError())
}
}
ignoreOpts := cmpopts.IgnoreFields(detectors.Result{}, "Raw", "VerificationError")
ignoreOpts := cmpopts.IgnoreFields(detectors.Result{}, "Raw", "verificationError")
if diff := cmp.Diff(got, tt.want, ignoreOpts); diff != "" {
t.Errorf("Azurestorage.FromData() %s diff: (-got +want)\n%s", tt.name, diff)
}
Expand Down
5 changes: 3 additions & 2 deletions pkg/detectors/betterstack/betterstack.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,11 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
} else if res.StatusCode == 401 {
// The secret is determinately not verified (nothing to do)
} else {
s1.VerificationError = fmt.Errorf("unexpected HTTP response status %d", res.StatusCode)
err = fmt.Errorf("unexpected HTTP response status %d", res.StatusCode)
s1.SetVerificationError(err, resMatch)
}
} else {
s1.VerificationError = err
s1.SetVerificationError(err, resMatch)
}
}

Expand Down
6 changes: 3 additions & 3 deletions pkg/detectors/betterstack/betterstack_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,11 @@ func TestBetterstack_FromChunk(t *testing.T) {
if len(got[i].Raw) == 0 {
t.Fatalf("no raw secret present: \n %+v", got[i])
}
if (got[i].VerificationError != nil) != tt.wantVerificationErr {
t.Fatalf("wantVerificationError = %v, verification error = %v", tt.wantVerificationErr, got[i].VerificationError)
if (got[i].VerificationError() != nil) != tt.wantVerificationErr {
t.Fatalf("wantVerificationError = %v, verification error = %v", tt.wantVerificationErr, got[i].VerificationError())
}
}
ignoreOpts := cmpopts.IgnoreFields(detectors.Result{}, "Raw", "VerificationError")
ignoreOpts := cmpopts.IgnoreFields(detectors.Result{}, "Raw", "verificationError")
if diff := cmp.Diff(got, tt.want, ignoreOpts); diff != "" {
t.Errorf("Betterstack.FromData() %s diff: (-got +want)\n%s", tt.name, diff)
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/detectors/bitcoinaverage/bitcoinaverage.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
if res.StatusCode >= 200 && res.StatusCode < 300 {
resp := &response{}
if err = json.NewDecoder(res.Body).Decode(resp); err != nil {
s1.VerificationError = err
s1.SetVerificationError(err, resMatch)
continue
}
if resp.Success {
Expand Down
2 changes: 1 addition & 1 deletion pkg/detectors/braintreepayments/braintreepayments.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
url := s.getBraintreeURL()
isVerified, verificationErr := verifyBraintree(ctx, client, url, resIdMatch, resMatch)
s1.Verified = isVerified
s1.VerificationError = verificationErr
s1.SetVerificationError(verificationErr, resMatch)
}

// This function will check false positives for common test words, but also it will make sure the key appears 'random' enough to be a real key
Expand Down
6 changes: 3 additions & 3 deletions pkg/detectors/braintreepayments/braintreepayments_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,12 +131,12 @@ func TestBraintreePayments_FromChunk(t *testing.T) {
if len(got[i].Raw) == 0 {
t.Fatalf("no raw secret present: \n %+v", got[i])
}
if (got[i].VerificationError != nil) != tt.wantVerificationErr {
t.Fatalf("wantVerificationError = %v, verification error = %v", tt.wantVerificationErr, got[i].VerificationError)
if (got[i].VerificationError() != nil) != tt.wantVerificationErr {
t.Fatalf("wantVerificationError = %v, verification error = %v", tt.wantVerificationErr, got[i].VerificationError())
}
}

ignoreOpts := cmpopts.IgnoreFields(detectors.Result{}, "Raw", "VerificationError")
ignoreOpts := cmpopts.IgnoreFields(detectors.Result{}, "Raw", "verificationError")
if diff := cmp.Diff(got, tt.want, ignoreOpts); diff != "" {
t.Errorf("BraintreePayments.FromData() %s diff: (-got +want)\n%s", tt.name, diff)
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/detectors/browserstack/browserstack.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result

isVerified, verificationErr := verifyBrowserStackCredentials(ctx, client, resUserMatch, resMatch)
s1.Verified = isVerified
s1.VerificationError = verificationErr
s1.SetVerificationError(verificationErr, resMatch)
}

// This function will check false positives for common test words, but also it will make sure the key appears 'random' enough to be a real key.
Expand Down
6 changes: 3 additions & 3 deletions pkg/detectors/browserstack/browserstack_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,11 +134,11 @@ func TestBrowserStack_FromChunk(t *testing.T) {
if len(got[i].Raw) == 0 {
t.Fatalf("no raw secret present: \n %+v", got[i])
}
if (got[i].VerificationError != nil) != tt.wantVerificationErr {
t.Fatalf("wantVerificationError = %v, verification error = %v", tt.wantVerificationErr, got[i].VerificationError)
if (got[i].VerificationError() != nil) != tt.wantVerificationErr {
t.Fatalf("wantVerificationError = %v, verification error = %v", tt.wantVerificationErr, got[i].VerificationError())
}
}
ignoreOpts := cmpopts.IgnoreFields(detectors.Result{}, "Raw", "VerificationError")
ignoreOpts := cmpopts.IgnoreFields(detectors.Result{}, "Raw", "verificationError")
if diff := cmp.Diff(got, tt.want, ignoreOpts); diff != "" {
t.Errorf("BrowserStack.FromData() %s diff: (-got +want)\n%s", tt.name, diff)
}
Expand Down
Loading

0 comments on commit 11394ea

Please sign in to comment.