Repository navigation
[INT-1091] Treat Square 403 as verified on INSUFFICIENT_SCOPES - #5367
Merged
Merged
Conversation
The Square detector treated every 403 as a live key. A 403 can also come from a TLS-intercepting proxy or security appliance, or from Square's own edge (rate limiting, bot protection). Those cases produced false "verified" results. The response body was also discarded, so there was nothing to diagnose them with. - Move verification into verifyMatch with an injectable HTTP client - Mark a 403 as verified only when Square's error body has code INSUFFICIENT_SCOPES - Report other 403s and unexpected statuses as verification errors that include the response body (read up to 4 KiB, cut to 512 bytes in the error, whitespace collapsed) - Add unit tests for 200, 401, 403 (scopes, HTML, other code, empty), 429, and body truncation
Corpora Test ResultsNo detector regex or keyword changes in this PR. Bench skipped. |
kvnphvm
approved these changes
Sep 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The Square detector treated every
403from the verification endpoint as a live key:A customer reported a key that the detector marked as verified, but a direct
curlto the Square API with the same key returned401. A403doesn't have to come from Square's credential check. For example:403looks like Square's answer.403for reasons unrelated to credential validity, such as rate limiting or bot protection.The detector also closed the response body without reading it, so there was nothing to show where the
403came from.Changes (
pkg/detectors/square/square.go)verifyMatch(ctx, client, token), and added an injectableclientonScanner(defaults tocommon.SaneHttpClient()). Results now go throughSetVerificationError.403, the body is parsed as Square's error envelope ({"errors":[{"category":...,"code":...,"detail":...}]}):200401403witherrors[].code == "INSUFFICIENT_SCOPES"403with any other body (HTML, other code, empty)unexpected 403 from Square: <body>429,5xx)unexpected HTTP response status <code>: <body>Other
403s are left indeterminate on purpose, not marked invalid. Marking them invalid would make a live key behind a blocking proxy look dead. With the body in the verification error, the user can see what actually answered.Tests (
pkg/detectors/square/square_test.go)Added
TestSquare_Verification, which runsFromDatawith a mocked HTTP client (common.ConstantResponseHttpClient) for these cases:200→ verified401→ unverified, no error403+INSUFFICIENT_SCOPES→ verified403+ HTML proxy page → indeterminate; the error contains the collapsed body403+ a different Square code (FORBIDDEN) → indeterminate403+ empty body → indeterminate (<empty body>)429→ indeterminate; the error contains the body500+ 10 KB body → the error is truncated to 512 bytesEach error case also checks that the token doesn't appear in the error message.
Checklist:
make test-community)?make lintthis requires golangci-lint)?Note
Medium Risk
Changes live/dead classification for Square API keys during scanning; behavior is more accurate but may alter verified counts for keys that previously matched any 403.
Overview
Tightens Square secret verification so a
403no longer automatically counts as a live key. Verification is moved intoverifyMatch, with an injectablehttp.ClientonScannerand errors surfaced viaSetVerificationError.A
403is verified only when the response body parses as Square’s error JSON witherrors[].code == "INSUFFICIENT_SCOPES". Other403s (HTML from a proxy, empty body, other codes) stay unverified and return an indeterminate verification error with a truncated, whitespace-collapsed body snippet—without leaking the token.401stays unverified; unexpected statuses (e.g.429,5xx) also produce verification errors. Response bodies are read with a 4 KiB cap before close.Tests:
TestSquare_Verificationmocks HTTP responses for 200, 401, scoped vs ambiguous 403s, rate limits, and large error bodies.Reviewed by Cursor Bugbot for commit b779208. Bugbot is set up for automated code reviews on this repo. Configure here.