Skip to content

Stripe Payment Intent Detector #4138

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

shahzadhaider1
Copy link
Contributor

@shahzadhaider1 shahzadhaider1 commented May 14, 2025

Description:

This PR introduces support for detecting Stripe PaymentIntent client secrets with comprehensive key-based verification.

Summary of Changes:

  • Added a new detector for identifying Stripe PaymentIntent client secrets (pi_*_secret_* format).
  • Implemented pattern matching logic to accurately detect client secrets and associated Stripe keys.
  • Added support for detecting live Stripe keys (secret keys: sk_live_/rk_live_ and publishable keys: pk_live_*).
  • Implemented comprehensive verification logic that creates individual results for each client secret + key combination.
  • Enhanced result structure to store client secrets in Raw field and client secret + key combinations in RawV2 field.

Key Implementation Details:

  • Multiple Result Generation: Creates one result for each client secret paired with each detected key (N client secrets × M keys = N×M results).
  • Conditional Processing: Only generates results when both client secrets AND keys are present in the data.
  • Live Keys Only: Focuses on live Stripe keys for security purposes (test keys are ignored).
  • Verification Logic: Each client secret + key combination is individually verified via Stripe API.

Verification Status:

  • Verification of client secrets is fully implemented and optimized.
  • When live Stripe keys are detected alongside client secrets, the detector attempts to verify each combination using the Stripe API.
  • Each client secret is tested against all available keys (both secret and publishable) to determine valid combinations.
  • Results are marked as verified only when the specific client secret + key combination is valid.
  • If no keys are found, no results are generated (preventing noise from standalone client secrets).

Result Structure:

  • Raw: Contains the client secret only
  • RawV2: Contains the client secret + key combination
  • Verified: Boolean indicating if this specific combination was verified via Stripe API

Testing:

  • Comprehensive unit tests covering multiple scenarios:
    • Single client secret with single key
    • Multiple client secrets with multiple keys
    • Mixed valid/invalid combinations
    • Edge cases (no keys, no client secrets, invalid patterns)
  • Integration tests with real Stripe API verification
  • Pattern matching tests ensuring only live keys are detected

Example Scenarios:

  • 2 client secrets + 3 keys = 6 individual results
  • Only valid combinations will be marked as verified
  • No results generated if keys are missing entirely

Checklist:

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

stripe-payment-intent-test

@shahzadhaider1 shahzadhaider1 requested review from a team as code owners May 14, 2025 08:13
@CLAassistant
Copy link

CLAassistant commented May 14, 2025

CLA assistant check
All committers have signed the CLA.

@shahzadhaider1 shahzadhaider1 marked this pull request as draft May 14, 2025 08:14
@shahzadhaider1 shahzadhaider1 force-pushed the feat/OSS-186-stripe-payment-intent branch from d86d855 to 5c6e35c Compare May 16, 2025 10:49
@shahzadhaider1 shahzadhaider1 marked this pull request as ready for review May 16, 2025 11:52
@shahzadhaider1 shahzadhaider1 force-pushed the feat/OSS-186-stripe-payment-intent branch from ce5a490 to 7166ebf Compare May 16, 2025 13:18
// Keywords are used for efficiently pre-filtering chunks.
// Use identifiers in the secret preferably, or the provider name.
func (s Scanner) Keywords() []string {
return []string{"pi_", "_secret_", "sk_live_", "rk_live_", "pk_live_"}
Copy link
Contributor

Choose a reason for hiding this comment

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

@shahzadhaider1 the keywords pi_ and _secret_, seem like they might occur quite frequently across many files and could result in a high number of false positives. The existing stripe detector only uses k_live_, I'm wondering if that would help make it more specific.

Copy link
Contributor

Choose a reason for hiding this comment

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

The existing stripe detector only uses k_live_, I'm wondering if that would help make it more specific.

pi_ or _secret_ are the only ones relevant to this specific detector. 🤷‍♂️

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As Richard also mentioned, pi_ and _secret_ keywords are relevant to this detector, so it wouldn't make sense to get rid of these keywords. Please let us know what do you think?

Copy link
Contributor

Choose a reason for hiding this comment

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

@rgmz @shahzadhaider1 since both substrings pi_ and _secret_ are part of the secret, I would suggest using only _secret_, since including both will theoretically yield more false matches, and pi_ looks like it may be more common out of the two, e.g. it would match inputs with that contain api_.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Alright. We have only _secret_ keyword now

@shahzadhaider1 shahzadhaider1 force-pushed the feat/OSS-186-stripe-payment-intent branch from 0516be7 to f7d6e1f Compare May 19, 2025 07:43
publishableKeys := extractMatches(publishableKeyPat, dataStr)

for clientSecret := range clientSecrets {
result := createResult(clientSecret, false, nil)
Copy link
Contributor

@kashifkhan0771 kashifkhan0771 May 19, 2025

Choose a reason for hiding this comment

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

If we pass verification as false, will the result only include client secrets without the secret key or publishable key? If so, the result would be largely meaningless in my opinion, since a client secret without either of those isn't useful on its own. We should create result only if we find either secret key or publishable key along with client secret. Than if verification fails we can mark it as unverified.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If we pass verification as false, will the result only include client secrets without the secret key or publishable key?

The result will always include only client secrets as the requirement for this detector is to detect client secrets in the Stripe Payment Intent objects. For detecting Stripe secret keys, we have another detector in place.

We should create result only if we find either secret key or publishable key along with client secret. Than if verification fails we can mark it as unverified.

I understand that client secret without a key is not very useful but since the requirement is to detect the client secrets and doing this will mean that if a data source contains only client secrets and no keys, we will never be able to detect the client secrets. Are you sure we want that?

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't want to be a blocker here. Just leaving my thoughts as a comment. If others feel the same as you do, feel free to move forward with this.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thank you for your feedback. I really appreciate it.
Let's see what other teammates suggest.

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree with @kashifkhan0771 that a client secret on its own does not seem to be meaningful unless a secret or publishable key is also detected, as you cannot use it or verify it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@kashifkhan0771 @nabeelalam I have updated the implementation based on your suggestion. I have also updated the PR description with latest implementation details. Please re-review and let me know what you think.

@shahzadhaider1 shahzadhaider1 force-pushed the feat/OSS-186-stripe-payment-intent branch from 1a90845 to 32a6a7c Compare May 19, 2025 15:37
Copy link
Contributor

@kashifkhan0771 kashifkhan0771 left a comment

Choose a reason for hiding this comment

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

LGTM!

@shahzadhaider1 shahzadhaider1 force-pushed the feat/OSS-186-stripe-payment-intent branch 3 times, most recently from 5a5b61d to 1a7e53c Compare May 22, 2025 10:45
Copy link
Contributor

@kashifkhan0771 kashifkhan0771 left a comment

Choose a reason for hiding this comment

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

Few non-blocking comments. The code looks clean to me!

@shahzadhaider1 shahzadhaider1 force-pushed the feat/OSS-186-stripe-payment-intent branch from 15c43d5 to 5eea834 Compare May 22, 2025 11:22
Comment on lines 146 to 147
case http.StatusOK:
return true, nil
Copy link
Contributor

Choose a reason for hiding this comment

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

Since the response contains the valid client_secret of a requested payment intent. Verification should be based on comparison of what is detected and what client_secret is in response. Does it make sense ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done - the implementation now reads the response body and verifies the detected client secret by comparing it with the value returned from the API, rather than relying solely on the API status code.

}{
{
name: "client secret with secret key",
input: "stripepaymentintent_token = '" + validClientSecret + "' and stripe_key = '" + validSecretKey + "'",
Copy link
Contributor

Choose a reason for hiding this comment

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

can we copy input variables values here directly? this is to improve the code readability.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done - I have removed all variables and used strings here directly.

@shahzadhaider1 shahzadhaider1 force-pushed the feat/OSS-186-stripe-payment-intent branch 2 times, most recently from 518d82e to 7af3f2b Compare May 23, 2025 13:25
@shahzadhaider1 shahzadhaider1 requested a review from abmussani May 23, 2025 13:26
@shahzadhaider1 shahzadhaider1 force-pushed the feat/OSS-186-stripe-payment-intent branch 2 times, most recently from df5712f to 9e51e97 Compare May 27, 2025 06:30
@shahzadhaider1 shahzadhaider1 force-pushed the feat/OSS-186-stripe-payment-intent branch from 9e51e97 to 6ee6227 Compare May 29, 2025 04:40
@shahzadhaider1 shahzadhaider1 force-pushed the feat/OSS-186-stripe-payment-intent branch from 6ee6227 to be42605 Compare May 29, 2025 11:28
Copy link
Contributor

@nabeelalam nabeelalam left a comment

Choose a reason for hiding this comment

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

Thanks for making all the updates @shahzadhaider1 !

@shahzadhaider1 shahzadhaider1 force-pushed the feat/OSS-186-stripe-payment-intent branch from be42605 to 21d6e08 Compare May 29, 2025 12:09
@zricethezav zricethezav merged commit 1ca22a6 into trufflesecurity:main May 29, 2025
13 checks passed
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.

7 participants