Skip to content

SEC-768: Send card details to Stripe in the request body, not the URL - #394

Draft
msuitcase wants to merge 1 commit into
masterfrom
security/SEC-768-stripe-card-details-in-body
Draft

msuitcase wants to merge 1 commit into
masterfrom
security/SEC-768-stripe-card-details-in-body

Conversation

@msuitcase

@msuitcase msuitcase commented Sep 18, 2026

Copy link
Copy Markdown

Description

ReferralCustomerService::createStripeToken passes card[number], card[exp_month], card[exp_year] and card[cvc] to Guzzle through the query request option, which places them in the URL query string of the POST https://api.stripe.com/v1/tokens request. Query strings are routinely captured by access logs, outbound proxies, APM/tracing tools and Referer headers, so cardholder data could be retained outside the payment path (PCI DSS requirement 3 / 4).

This change switches the option to form_params, so Guzzle sends the same nested card[...] fields as an application/x-www-form-urlencoded body, which is what Stripe expects on this endpoint (and what easypost-ruby, easypost-go and easypost-csharp already do). The explicit Content-Type header is kept; Guzzle honours a caller-supplied header alongside form_params.

Also adds a Next Release CHANGELOG entry.

Tracking: SEC-768 (internal).

Testing

  • No PHP on the machine I authored this from, so phpunit / phpstan have not been run here; the change is a one-key rename in the Guzzle options array. Please run the suite in CI.
  • Cassette re-record needed: test/cassettes/referral_customers/addCreditCard.yml was recorded with the card fields in the query string, so testAddCreditCard will not replay under php-vcr's default matchers until re-recorded with PARTNER_USER_PROD_API_KEY / REFERRAL_CUSTOMER_PROD_API_KEY. I do not have those keys. When re-recording, please confirm the recorded URL no longer carries card fields and that the request-body scrubber covers them.

Pull Request Type

Please select the option(s) that are relevant to this PR.

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Improvement (fixing a typo, updating readme, renaming a variable name, etc)

🤖 Generated with Claude Code

`referralCustomer->addCreditCard` passed the card number, expiry and CVC to
Guzzle via the `query` option, which puts them in the URL query string of the
`POST /v1/tokens` request. Use `form_params` so the same form-encoded fields
go in the request body, keeping cardholder data out of access logs, proxy
logs, tracing tools and Referer headers.

SEC-768

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
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.

1 participant