Add Google OAuth2 Client Secret detector#5030
Conversation
This commit adds a comprehensive detector for Google OAuth2 Client Secrets:
- Detects GOCSPX- prefix followed by exactly 28 base64url-safe characters
- Verifies secrets against Google's OAuth2 token endpoint
- Pairs secrets with client IDs when both are present in the same data
- Interprets Google's error responses to distinguish valid vs invalid credentials
- Includes comprehensive test coverage with mock server verification
The detector adds GoogleClientSecret (ID 1053) to the detector type enum and
follows TruffleHog's best practices for secret detection and verification.
Key features:
- Pattern matching: GOCSPX-[0-9A-Za-z_-]{28}
- Optional client ID pairing: [digits]-[token].apps.googleusercontent.com
- Verification via OAuth2 token endpoint with placeholder grant
- Error response classification:
* invalid_grant/invalid_request → credentials recognized (verified)
* unauthorized_client → credentials recognized (verified)
* invalid_client → credentials not recognized (unverified)
- Proper SecretParts population with RawV2 for paired credentials
- Rotation guide in ExtraData
Verification Strategy:
The detector sends a token exchange request with a placeholder authorization
code to Google's OAuth2 endpoint. Google validates the client_id + client_secret
pair before checking the authorization code, allowing us to verify credentials
without needing a real OAuth flow. The error response type indicates whether
the credentials are genuine.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
| switch errResp.Error { | ||
| case "invalid_grant", "invalid_request": | ||
| // Credentials are known to Google; the grant/request itself is invalid. | ||
| return true, extraData, nil |
There was a problem hiding this comment.
invalid_request marked verified despite unchecked credentials
Medium Severity
The function's own doc comment on line 125 states that invalid_request is triggered "before credential checks," meaning Google has not validated the secret. Yet the code on line 174 treats this response as verified = true. If the comment is accurate, this causes false positives — any secret (valid or not) that triggers invalid_request would be incorrectly reported as a verified credential. The inline switch comment ("Credentials are known to Google") contradicts the doc comment.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 13047a9. Configure here.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…m/asivaprasad09/trufflehog into add-google-client-secret-detector
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
There are 2 total unresolved issues (including 1 from previous review).
Reviewed by Cursor Bugbot for commit 4186815. Configure here.
| case http.StatusUnauthorized: | ||
| if errResp.Error == "unauthorized_client" { | ||
| return true, extraData, nil | ||
| } |
There was a problem hiding this comment.
unauthorized_client checked under wrong HTTP status code
Medium Severity
The unauthorized_client error is only handled under http.StatusUnauthorized (401), but per RFC 6749 §5.2 the OAuth2 token endpoint returns this error with HTTP 400. Google can also return it with 400. The existing boxoauth detector in this codebase correctly handles unauthorized_client under StatusBadRequest. When Google returns unauthorized_client with a 400 status, the inner switch falls through (it doesn't match "invalid_grant", "invalid_request", or "invalid_client"), then the outer switch also falls through, producing a spurious verification error instead of marking valid credentials as verified.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 4186815. Configure here.


Summary
This PR adds a comprehensive detector for Google OAuth2 Client Secrets (GOCSPX- prefix) used to authenticate server-side OAuth2 flows.
Key features:
GOCSPX-prefix followed by exactly 28 base64url-safe charactersChanges
GoogleClientSecret(ID 1053) toproto/detector_type.protopkg/detectors/googleclientsecret/pkg/engine/defaults/defaults.goPattern Details
The detector uses two regex patterns:
Client Secret Pattern:
GOCSPX-prefix[0-9A-Za-z_-]Client ID Pattern (optional pairing):
.apps.googleusercontent.comRawV2Testing
All tests pass successfully:
Test coverage includes:
Pattern matching tests:
client_secretfieldsVerification tests with mock server:
Verification Strategy
The detector verifies secrets by sending a token exchange request to Google's OAuth2 endpoint:
Why this works: Google validates the
client_id+client_secretpair before checking the authorization code. This allows us to verify credentials without needing a real OAuth flow.Error response classification:
invalid_grant→ Credentials are valid; the grant itself is invalid ✅ Verifiedinvalid_request→ Credentials are valid; request format issue ✅ Verifiedunauthorized_client→ Credentials are valid; client type restriction ✅ Verifiedinvalid_client→ Credentials not recognized ❌ UnverifiedVerificationErrorfor investigationClient ID handling:
000000000000-placeholder.apps.googleusercontent.comSecretParts Population
The detector properly populates
SecretParts:When both secret and client ID are present:
ExtraData includes:
Example Matches
✅ Will detect:
{ "client_id": "123456789012-abc123.apps.googleusercontent.com", "client_secret": "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" }❌ Will NOT detect (invalid format):
Security Impact
What this secret enables:
Why detection matters:
Google Client Secrets are long-lived credentials often stored in configuration files, environment variables, and version control. Exposure allows attackers to bypass application-level access controls and obtain user authorization tokens.
Design Rationale
Why GOCSPX- prefix?
Google introduced this prefix in 2021 to make client secrets more easily identifiable and scannable. The prefix is unique to Google OAuth2 client secrets.
Why 28 characters exactly?
This is Google's fixed format for GOCSPX- secrets. The strict length requirement reduces false positives significantly.
Why use placeholder authorization code?
The OAuth2 token endpoint validates credentials before validating the authorization code, allowing credential verification without a complete OAuth flow. This is a common technique for verifying OAuth credentials.
Why pair with client ID?
Client secrets are always used with their corresponding client ID. When both are present in the same chunk, pairing them:
RawV2🤖 Generated with Claude Code
Note
Medium Risk
Verification sends discovered client secrets to Google's live OAuth token endpoint, which is sensitive credential handling; otherwise the change is additive detector plumbing with tests.
Overview
Adds a Google OAuth2 client secret (
GOCSPX-) detector and wires it into the default engine asGoogleClientSecret(proto ID 1053).The scanner matches the
GOCSPX-+ 28-character token pattern (keywordGOCSPX-), optionally pairs a.apps.googleusercontent.comclient ID in the same chunk intoRawV2, and when verification is on posts a dummy authorization-code exchange tooauth2.googleapis.com/token, treatinginvalid_grant/invalid_request/unauthorized_clientas verified andinvalid_clientas not. Results include rotation metadata and OAuth error fields inExtraData. Unit tests cover pattern cases and mock HTTP verification.Reviewed by Cursor Bugbot for commit 4186815. Bugbot is set up for automated code reviews on this repo. Configure here.