Skip to content

Commit 2e998e4

Browse files
authored
Merge branch 'main' into aman.handlers-embed-small-fixtures
2 parents 494c02e + 5a0f877 commit 2e998e4

6 files changed

Lines changed: 60 additions & 17 deletions

File tree

main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,7 @@ func run(state overseer.State, logSync func() error) {
532532
feature.PineconeDetectorEnabled.Store(true)
533533
feature.CloudinaryDetectorEnabled.Store(true)
534534
feature.GitLabOAuthDetectorEnabled.Store(true)
535+
feature.EnigmaDetectorEnabled.Store(true)
535536

536537
conf := &config.Config{}
537538
if *configFilename != "" {

pkg/detectors/enigma/enigma.go

Lines changed: 48 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package enigma
22

33
import (
44
"context"
5+
"fmt"
6+
"io"
57
"net/http"
68
"strings"
79

@@ -33,7 +35,6 @@ func (s Scanner) Keywords() []string {
3335
// FromData will find and optionally verify Enigma secrets in a given set of bytes.
3436
func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (results []detectors.Result, err error) {
3537
dataStr := string(data)
36-
3738
matches := keyPat.FindAllStringSubmatch(dataStr, -1)
3839

3940
for _, match := range matches {
@@ -46,20 +47,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
4647
}
4748

4849
if verify {
49-
payload := strings.NewReader(`{"name":"Enigma Technologies, Inc.","person":{"first_name":"","last_name":""},"address":{"street_address1":"245 5th Ave","street_address2":"","city":"New York","state":"NY","postal_code":"10016"}}`)
50-
req, err := http.NewRequestWithContext(ctx, "POST", "https://api.enigma.com/businesses/match", payload)
51-
if err != nil {
52-
continue
53-
}
54-
req.Header.Add("Content-Type", "application/json")
55-
req.Header.Add("x-api-key", resMatch)
56-
res, err := client.Do(req)
57-
if err == nil {
58-
defer func() { _ = res.Body.Close() }()
59-
if res.StatusCode >= 200 && res.StatusCode < 300 {
60-
s1.Verified = true
61-
}
62-
}
50+
isVerified, verificationErr := verifyKey(ctx, client, resMatch)
51+
s1.Verified = isVerified
52+
s1.SetVerificationError(verificationErr, resMatch)
6353
}
6454

6555
results = append(results, s1)
@@ -68,10 +58,52 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
6858
return results, nil
6959
}
7060

61+
// verifyKey checks an Enigma API key against the GraphQL endpoint.
62+
//
63+
// The query selects only `__typename`, which the GraphQL spec guarantees on
64+
// every root type, so verification does not depend on Enigma's evolving schema
65+
// or any specific entity id. Authentication is driven by the HTTP status code:
66+
// 200 means the key is valid, 401 mean it is not.
67+
//
68+
// A 200 is additionally guarded by a JSON Content-Type check: server could return
69+
// a 200 HTML block page, which we must not mistake for a live key.
70+
func verifyKey(ctx context.Context, client *http.Client, key string) (bool, error) {
71+
payload := strings.NewReader(`{"query":"{ __typename }"}`)
72+
73+
req, err := http.NewRequestWithContext(ctx, http.MethodPost, "https://api.enigma.com/graphql", payload)
74+
if err != nil {
75+
return false, err
76+
}
77+
req.Header.Add("Content-Type", "application/json")
78+
req.Header.Add("x-api-key", key)
79+
80+
res, err := client.Do(req)
81+
if err != nil {
82+
return false, err
83+
}
84+
defer func() {
85+
_, _ = io.Copy(io.Discard, res.Body)
86+
_ = res.Body.Close()
87+
}()
88+
89+
switch res.StatusCode {
90+
case http.StatusOK:
91+
if contentType := res.Header.Get("Content-Type"); !strings.Contains(contentType, "application/json") {
92+
return false, fmt.Errorf("got HTTP 200 with unexpected Content-Type %q", contentType)
93+
}
94+
95+
return true, nil
96+
case http.StatusUnauthorized:
97+
return false, nil
98+
default:
99+
return false, fmt.Errorf("unexpected HTTP response status %d", res.StatusCode)
100+
}
101+
}
102+
71103
func (s Scanner) Type() detector_typepb.DetectorType {
72104
return detector_typepb.DetectorType_Enigma
73105
}
74106

75107
func (s Scanner) Description() string {
76-
return "Enigma is a data intelligence company that provides comprehensive data about businesses. Enigma API keys can be used to access and interact with this data."
108+
return "Enigma is a business data intelligence platform. Enigma API keys grant access to comprehensive firmographic, legal, and identity datasets."
77109
}

pkg/detectors/enigma/enigma_integration_test.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import (
1919
func TestEnigma_FromChunk(t *testing.T) {
2020
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
2121
defer cancel()
22-
testSecrets, err := common.GetSecret(ctx, "trufflehog-testing", "detectors1")
22+
testSecrets, err := common.GetSecret(ctx, "trufflehog-testing", "detectors6")
2323
if err != nil {
2424
t.Fatalf("could not get test secrets from GCP: %s", err)
2525
}
@@ -50,6 +50,9 @@ func TestEnigma_FromChunk(t *testing.T) {
5050
{
5151
DetectorType: detector_typepb.DetectorType_Enigma,
5252
Verified: true,
53+
SecretParts: map[string]string{
54+
"key": secret,
55+
},
5356
},
5457
},
5558
wantErr: false,
@@ -66,6 +69,9 @@ func TestEnigma_FromChunk(t *testing.T) {
6669
{
6770
DetectorType: detector_typepb.DetectorType_Enigma,
6871
Verified: false,
72+
SecretParts: map[string]string{
73+
"key": inactiveSecret,
74+
},
6975
},
7076
},
7177
wantErr: false,

pkg/engine/defaults/defaults.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1778,6 +1778,8 @@ func buildDetectorList() []detectors.Detector {
17781778
return !feature.CloudinaryDetectorEnabled.Load()
17791779
case *gitlaboauth2.Scanner:
17801780
return !feature.GitLabOAuthDetectorEnabled.Load()
1781+
case *enigma.Scanner:
1782+
return !feature.EnigmaDetectorEnabled.Load()
17811783
default:
17821784
return false
17831785
}

pkg/engine/defaults/defaults_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ var excludedFromDefaultList = map[detector_typepb.DetectorType]struct{}{
119119
// Remove each entry once its detector has been carefully added.
120120
detector_typepb.DetectorType_Cloudinary: {},
121121
detector_typepb.DetectorType_DatadogApikey: {},
122+
detector_typepb.DetectorType_Enigma: {},
122123
detector_typepb.DetectorType_GitLabOauth2: {},
123124
detector_typepb.DetectorType_Guru: {},
124125
detector_typepb.DetectorType_IPInfo: {},

pkg/feature/feature.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ var (
1919
PineconeDetectorEnabled atomic.Bool
2020
CloudinaryDetectorEnabled atomic.Bool
2121
GitLabOAuthDetectorEnabled atomic.Bool
22+
EnigmaDetectorEnabled atomic.Bool
2223
)
2324

2425
type AtomicString struct {

0 commit comments

Comments
 (0)