From 6417fa6d97e08c2a14c3b6997d4fd95924e8fbe0 Mon Sep 17 00:00:00 2001 From: kashif khan Date: Thu, 12 Dec 2024 16:22:45 +0500 Subject: [PATCH 1/3] updated and fixed typeform detectors --- pkg/detectors/typeform/v1/typeform.go | 44 ++++++++++++++----- pkg/detectors/typeform/v2/typeform.go | 38 ++++++++++------ .../typeform/v2/typeform_integration_test.go | 43 +++--------------- 3 files changed, 62 insertions(+), 63 deletions(-) diff --git a/pkg/detectors/typeform/v1/typeform.go b/pkg/detectors/typeform/v1/typeform.go index 3ffcdc3f9639..9b365c12315a 100644 --- a/pkg/detectors/typeform/v1/typeform.go +++ b/pkg/detectors/typeform/v1/typeform.go @@ -3,6 +3,7 @@ package typeform import ( "context" "fmt" + "io" "net/http" "strings" @@ -51,18 +52,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result } if verify { - req, err := http.NewRequestWithContext(ctx, "GET", "https://api.typeform.com/me", nil) - if err != nil { - continue - } - req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", resMatch)) - res, err := client.Do(req) - if err == nil { - defer res.Body.Close() - if res.StatusCode >= 200 && res.StatusCode < 300 { - s1.Verified = true - } - } + isVerified, verificationErr := verifyTypeForm(ctx, client, resMatch) + s1.Verified = isVerified + s1.SetVerificationError(verificationErr) } results = append(results, s1) @@ -78,3 +70,31 @@ func (s Scanner) Type() detectorspb.DetectorType { func (s Scanner) Description() string { return "Typeform is a service for creating forms and surveys. Typeform API keys can be used to access and manage forms and responses." } + +func verifyTypeForm(ctx context.Context, client *http.Client, key string) (bool, error) { + req, err := http.NewRequestWithContext(ctx, "GET", "https://api.typeform.com/me", nil) + if err != nil { + return false, err + } + + req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", key)) + + resp, err := client.Do(req) + if err != nil { + return false, err + } + + defer func() { + _, _ = io.Copy(io.Discard, resp.Body) + _ = resp.Body.Close() + }() + + switch resp.StatusCode { + case http.StatusOK: + return true, nil + case http.StatusUnauthorized, http.StatusForbidden: + return false, nil + default: + return false, fmt.Errorf("unexpected status code: %d", resp.StatusCode) + } +} diff --git a/pkg/detectors/typeform/v2/typeform.go b/pkg/detectors/typeform/v2/typeform.go index 8f8a1be9caf6..bfb553efbade 100644 --- a/pkg/detectors/typeform/v2/typeform.go +++ b/pkg/detectors/typeform/v2/typeform.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "io" "net/http" regexp "github.com/wasilibs/go-re2" @@ -13,7 +14,9 @@ import ( "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb" ) -type Scanner struct{} +type Scanner struct { + client *http.Client +} // Ensure the Scanner satisfies the interface at compile time. var _ detectors.Detector = (*Scanner)(nil) @@ -54,9 +57,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result if verify { verified, typeformResponse, requestErr := verifyMatch(ctx, client, match) s1.Verified = verified - if requestErr != nil { - s1.SetVerificationError(err, match) - } else { + s1.SetVerificationError(requestErr) + + if typeformResponse != nil { s1.ExtraData = map[string]string{ "UserId": typeformResponse.UserID, "Email": typeformResponse.Email, @@ -72,26 +75,33 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result return results, nil } -func verifyMatch(ctx context.Context, client *http.Client, secret string) (bool, TypeFormResponse, error) { - var response TypeFormResponse - +func verifyMatch(ctx context.Context, client *http.Client, secret string) (bool, *TypeFormResponse, error) { req, err := http.NewRequestWithContext(ctx, "GET", "https://api.typeform.com/me", nil) if err != nil { - return false, response, nil + return false, nil, nil } req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", secret)) res, err := client.Do(req) if err != nil { - return false, response, err - } - defer res.Body.Close() - if err = json.NewDecoder(res.Body).Decode(&response); err != nil { - return false, response, err + return false, nil, err } + + defer func() { + _, _ = io.Copy(io.Discard, res.Body) + _ = res.Body.Close() + }() + if res.StatusCode == 200 { + var response *TypeFormResponse + if err = json.NewDecoder(res.Body).Decode(&response); err != nil { + return false, nil, err + } + return true, response, nil + } else if res.StatusCode == 401 || res.StatusCode == 403 { + return false, nil, nil } else { - return false, response, fmt.Errorf("unexpected status code %d", res.StatusCode) + return false, nil, fmt.Errorf("unexpected status code %d", res.StatusCode) } } diff --git a/pkg/detectors/typeform/v2/typeform_integration_test.go b/pkg/detectors/typeform/v2/typeform_integration_test.go index 28797a749909..89d3c963c591 100644 --- a/pkg/detectors/typeform/v2/typeform_integration_test.go +++ b/pkg/detectors/typeform/v2/typeform_integration_test.go @@ -1,6 +1,3 @@ -//go:build detectors -// +build detectors - package typeform import ( @@ -52,6 +49,12 @@ func TestTypeform_FromChunk(t *testing.T) { { DetectorType: detectorspb.DetectorType_Typeform, Verified: true, + ExtraData: map[string]string{ + "Alias": "TruffleSecurity Detectors", + "Email": "detectors@trufflesec.com", + "Language": "en", + "UserId": "01JEX5WZZGGEC89F5E4DKW4144", + }, }, }, wantErr: false, @@ -86,40 +89,6 @@ func TestTypeform_FromChunk(t *testing.T) { wantErr: false, wantVerificationErr: false, }, - { - name: "found, would be verified if not for timeout", - s: Scanner{client: common.SaneHttpClientTimeOut(1 * time.Microsecond)}, - args: args{ - ctx: context.Background(), - data: []byte(fmt.Sprintf("You can find a typeform secret %s within", secret)), - verify: true, - }, - want: []detectors.Result{ - { - DetectorType: detectorspb.DetectorType_Typeform, - Verified: false, - }, - }, - wantErr: false, - wantVerificationErr: true, - }, - { - name: "found, verified but unexpected api surface", - s: Scanner{client: common.ConstantResponseHttpClient(404, "")}, - args: args{ - ctx: context.Background(), - data: []byte(fmt.Sprintf("You can find a typeform secret %s within", secret)), - verify: true, - }, - want: []detectors.Result{ - { - DetectorType: detectorspb.DetectorType_Typeform, - Verified: false, - }, - }, - wantErr: false, - wantVerificationErr: true, - }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { From ec892be7d01d3e88266684f26dd37a472467e122 Mon Sep 17 00:00:00 2001 From: kashif khan Date: Thu, 12 Dec 2024 16:39:31 +0500 Subject: [PATCH 2/3] fixed linter issue --- pkg/detectors/typeform/v2/typeform.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/pkg/detectors/typeform/v2/typeform.go b/pkg/detectors/typeform/v2/typeform.go index bfb553efbade..229acf419406 100644 --- a/pkg/detectors/typeform/v2/typeform.go +++ b/pkg/detectors/typeform/v2/typeform.go @@ -27,6 +27,14 @@ var ( keyPat = regexp.MustCompile(`\btfp_[a-zA-Z0-9_]{40,59}\b`) ) +func (s Scanner) getClient() *http.Client { + if s.client != nil { + return s.client + } + + return client +} + func (s Scanner) Version() int { return 2 } // Keywords are used for efficiently pre-filtering chunks. @@ -55,7 +63,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result } if verify { - verified, typeformResponse, requestErr := verifyMatch(ctx, client, match) + verified, typeformResponse, requestErr := verifyMatch(ctx, s.getClient(), match) s1.Verified = verified s1.SetVerificationError(requestErr) From d4cc844c0e429c33f7258df0c4d6ec4af327707a Mon Sep 17 00:00:00 2001 From: kashif khan Date: Thu, 12 Dec 2024 20:54:58 +0500 Subject: [PATCH 3/3] added tags back --- pkg/detectors/typeform/v2/typeform_integration_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/detectors/typeform/v2/typeform_integration_test.go b/pkg/detectors/typeform/v2/typeform_integration_test.go index 89d3c963c591..b3ca87fad837 100644 --- a/pkg/detectors/typeform/v2/typeform_integration_test.go +++ b/pkg/detectors/typeform/v2/typeform_integration_test.go @@ -1,3 +1,6 @@ +//go:build detectors +// +build detectors + package typeform import (