Skip to content

Fix custom detector verification: add retry, configurable success ranges, and inconclusive state#4821

Open
shahzadhaider1 wants to merge 3 commits intotrufflesecurity:mainfrom
shahzadhaider1:INS-408-custom-detectors-verification-logic-update
Open

Fix custom detector verification: add retry, configurable success ranges, and inconclusive state#4821
shahzadhaider1 wants to merge 3 commits intotrufflesecurity:mainfrom
shahzadhaider1:INS-408-custom-detectors-verification-logic-update

Conversation

@shahzadhaider1
Copy link
Contributor

@shahzadhaider1 shahzadhaider1 commented Mar 17, 2026

Summary

Fixes three issues with custom detector verification that caused false negatives and poor resilience against transient failures:

  • Retry on transient errors: Switched from SaneHttpClient to RetryableHTTPClient, giving custom detectors automatic retry with exponential backoff on 429 (rate-limit) and 5xx responses (3 retries).
  • Configurable success status codes: Wired up the existing but unused successRanges field on VerifierConfig. Users can now specify status codes (e.g. "403") or ranges (e.g. "200-299") that count as verified. Defaults to 200 only when no ranges are configured (backward compatible). Validation via ValidateVerifyRanges is now called during detector initialization.
  • Inconclusive state via SetVerificationError: Network failures and timeouts now call result.SetVerificationError(err) instead of silently leaving Verified = false. This marks the result as "unknown" (inconclusive) rather than definitively unverified, preventing false negatives. A subsequent verify config that responds with a clear non-success status will clear the error via ClearVerificationError(). This matches the three-state model used by built-in detectors (Slack, SendGrid, OpenAI, etc.) and integrates with the existing --results=unknown filtering in the engine.

Changes

  • pkg/custom_detectors/custom_detectors.go: retryable client, success ranges check, verification error handling, isStatusInRanges helper
  • pkg/detectors/detectors.go: added ClearVerificationError() method on Result
  • pkg/custom_detectors/custom_detectors_test.go: tests for success ranges, verification error on network failure, error clearing on definitive rejection, invalid range validation

Checklist:

  • Tests passing (make test-community)?
  • Lint passing (make lint this requires golangci-lint)?

Note

Medium Risk
Changes custom detector verification semantics and HTTP behavior (retries, configurable success status codes, and new inconclusive error state), which may affect verified/unverified classification and downstream filtering.

Overview
Custom detector webhook verification is now more resilient and expressive. Verification requests switch to common.RetryableHTTPClient() and network failures/timeouts now set a verification error (inconclusive) instead of silently leaving results unverified.

Verification success is now determined by configurable successRanges (single codes like "403" or ranges like "200-299"), validated during NewWebhookCustomRegex init and implemented via isStatusInRanges. Adds Result.ClearVerificationError() and logic to clear prior inconclusive errors when a later verifier gives a definitive non-success or success response, with new tests covering these behaviors and invalid ranges.

Written by Cursor Bugbot for commit 625c881. This will update automatically on new commits. Configure here.

@shahzadhaider1 shahzadhaider1 requested a review from a team March 17, 2026 16:27
@shahzadhaider1 shahzadhaider1 requested a review from a team as a code owner March 17, 2026 16:27
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

}

var httpClient = common.SaneHttpClient()
var httpClient = common.RetryableHTTPClient()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Retryable client may mask user-configured success status codes

Medium Severity

RetryableHTTPClient automatically retries 429 and 5xx responses (via ErrorPropagatedRetryPolicy), but users can now configure those same codes as success via successRanges. If a server returns e.g. 429 (user considers it "verified") and the retry yields 200 (not in their successRanges), isStatusInRanges returns false — producing a false negative. The two features introduced in this PR conflict with each other for retry-eligible status codes.

Additional Locations (1)
Fix in Cursor Fix in Web

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm. Users would configure 429 and 5xx as success status codes?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn’t make assumptions when offering a custom detector option. It needs to remain fully configurable, even for cases we might think aren’t necessary. If a retryable client is desired, it should also be exposed through configuration, with a clear warning that enabling it will retry on 429/500 status codes. Otherwise, users can stick with the simple client.

}

// ClearVerificationError resets the verification error to nil.
func (r *Result) ClearVerificationError() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not understand the purpose of this? Why would we want to add a verification error to the result and than remove it later? In which scenarios this will be useful?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants