Skip to content

Commit b8142ba

Browse files
committed
fixup of tests
1 parent 924f402 commit b8142ba

File tree

2 files changed

+74
-31
lines changed

2 files changed

+74
-31
lines changed

pkg/detectors/gcpoauth2/gcpoauth2.go

Lines changed: 70 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,8 @@ type Scanner struct {
1616
detectors.DefaultMultiPartCredentialProvider
1717
}
1818

19-
// Ensure the Scanner satisfies the interface at compile time.
2019
var _ detectors.Detector = (*Scanner)(nil)
2120

22-
// GCP Oauth2 Client ID and secret regex patterns.
2321
var (
2422
oauth2ClientID = regexp.MustCompile("[0-9a-zA-Z\\-_]{16,}\\.apps\\.googleusercontent\\.com")
2523
oauth2ClientSecret = regexp.MustCompile("GOCSPX-[0-9a-zA-Z\\-_]{20,}")
@@ -29,10 +27,8 @@ const (
2927
gcpOAuthBadVerificationCodeError = "bad_verification_code"
3028
)
3129

32-
// Keywords are used for efficiently pre-filtering chunks.
33-
// Use identifiers in the secret preferably, or the provider name.
3430
func (s Scanner) Keywords() []string {
35-
return []string{".apps.googleusercontent.com", "GOCSPX-"}
31+
return []string{".apps.googleusercontent.com", "GOCSPX-", "oauth2_client_id", "oauth2_client_secret"}
3632
}
3733

3834
func (s Scanner) Type() detectorspb.DetectorType {
@@ -43,40 +39,87 @@ func (s Scanner) Description() string {
4339
return "GCP OAuth2 credentials are sensitive strings (client ID and secret) issued by Google Cloud to identify your application and securely authorize its access to Google APIs on behalf of users."
4440
}
4541

46-
// FromData will find and optionally verify GitHub secrets in a given set of bytes.
4742
func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (results []detectors.Result, err error) {
4843
dataStr := string(data)
4944

50-
// Oauth2 client ID and secret
5145
oauth2ClientIDMatches := oauth2ClientID.FindAllStringSubmatch(dataStr, -1)
5246
oauth2ClientSecretMatches := oauth2ClientSecret.FindAllStringSubmatch(dataStr, -1)
5347

54-
for _, idMatch := range oauth2ClientIDMatches {
55-
for _, secretMatch := range oauth2ClientSecretMatches {
56-
57-
s1 := detectors.Result{
58-
DetectorType: detectorspb.DetectorType_GoogleOauth2,
59-
Raw: []byte(idMatch[1]),
60-
RawV2: []byte(idMatch[1] + secretMatch[1]),
48+
seen := make(map[string]bool)
49+
50+
pairedIDs := make(map[string]bool)
51+
pairedSecrets := make(map[string]bool)
52+
53+
if len(oauth2ClientIDMatches) > 0 && len(oauth2ClientSecretMatches) > 0 {
54+
for _, idMatch := range oauth2ClientIDMatches {
55+
for _, secretMatch := range oauth2ClientSecretMatches {
56+
clientID := idMatch[0]
57+
clientSecret := secretMatch[0]
58+
key := "pair:" + clientID + ":" + clientSecret
59+
60+
if !seen[key] {
61+
seen[key] = true
62+
pairedIDs[clientID] = true
63+
pairedSecrets[clientSecret] = true
64+
65+
s1 := detectors.Result{
66+
DetectorType: detectorspb.DetectorType_GoogleOauth2,
67+
Raw: []byte(clientID),
68+
RawV2: []byte(clientID + clientSecret),
69+
}
70+
71+
if verify {
72+
config := &clientcredentials.Config{
73+
ClientID: clientID,
74+
ClientSecret: clientSecret,
75+
TokenURL: google.Endpoint.TokenURL,
76+
}
77+
_, err := config.Token(ctx)
78+
if err != nil && strings.Contains(err.Error(), gcpOAuthBadVerificationCodeError) {
79+
s1.Verified = true
80+
}
81+
}
82+
83+
results = append(results, s1)
84+
}
6185
}
86+
}
87+
}
6288

63-
config := &clientcredentials.Config{
64-
ClientID: idMatch[1],
65-
ClientSecret: secretMatch[1],
66-
TokenURL: google.Endpoint.TokenURL,
67-
}
68-
if verify {
69-
_, err := config.Token(ctx)
70-
// if client id and client secret is correct, it will return bad verification code error as we do not pass any verification code
71-
if err != nil && strings.Contains(err.Error(), gcpOAuthBadVerificationCodeError) {
72-
// mark result as verified only in case of bad verification code error, for any other error the result will be unverified
73-
s1.Verified = true
89+
// Process orphan ClientID-only matches (not part of any pair)
90+
if len(oauth2ClientIDMatches) > 0 && len(pairedIDs) == 0 {
91+
for _, idMatch := range oauth2ClientIDMatches {
92+
clientID := idMatch[0]
93+
key := "id:" + clientID
94+
95+
if !pairedIDs[clientID] && !seen[key] {
96+
seen[key] = true
97+
s1 := detectors.Result{
98+
DetectorType: detectorspb.DetectorType_GoogleOauth2,
99+
Raw: []byte(clientID),
100+
RawV2: []byte(clientID),
74101
}
102+
results = append(results, s1)
75103
}
76-
77-
results = append(results, s1)
78104
}
79105
}
80106

107+
// Process orphan ClientSecret-only matches (not part of any pair)
108+
if len(oauth2ClientSecretMatches) > 0 && len(pairedSecrets) == 0 {
109+
for _, secretMatch := range oauth2ClientSecretMatches {
110+
clientSecret := secretMatch[0]
111+
key := "secret:" + clientSecret
112+
113+
if !pairedSecrets[clientSecret] && !seen[key] {
114+
seen[key] = true
115+
s1 := detectors.Result{
116+
DetectorType: detectorspb.DetectorType_GoogleOauth2,
117+
Raw: []byte(clientSecret),
118+
RawV2: []byte(clientSecret),
119+
}
120+
results = append(results, s1)
121+
}
122+
}
123+
}
81124
return
82125
}

pkg/detectors/gcpoauth2/gcpoauth2_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,11 @@ func TestGcpOAuth2_Pattern(t *testing.T) {
3333
},
3434
},
3535
{
36-
name: "typical pattern - multiline with both client_id and client_secret",
37-
input: "oauth2_client_id = '1234567890-abc123def456ghi789jkl012mno345pq.apps.googleusercontent.com'\noauth2_client_secret = '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'",
36+
name: "typical pattern - multiline with both keywords",
37+
input: `oauth2_client_id = '1234567890-abc123def456ghi789jkl012mno345pq.apps.googleusercontent.com'
38+
oauth2_client_secret = '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'`,
3839
want: []string{
39-
"1234567890-abc123def456ghi789jkl012mno345pq.apps.googleusercontent.com",
40-
"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",
40+
"1234567890-abc123def456ghi789jkl012mno345pq.apps.googleusercontent.comGOCSPX-5aBcD3fgHiJK_lMnOpQRstuVwXyZ",
4141
},
4242
},
4343
{

0 commit comments

Comments
 (0)