PCI DSS for SaaS Touching Payments: Patterns to Avoid the Trap
PCI DSS (Payment Card Industry Data Security Standard) is a set of security requirements for organizations that process, transmit, or store payment card data. Compliance scope is determined by the cardholder data environment (CDE): the systems and people who can access cardholder data. The most effective PCI DSS strategy for SaaS products is reducing the CDE to zero by using payment processor tokenization so that card data never touches the application's infrastructure.
What you need to know
- The best PCI strategy is to make card data never touch your infrastructure. Use hosted payment fields (Stripe.js, Braintree Hosted Fields) that collect card data in an iframe owned by the processor.
- SAQ A eligibility requires that the payment form is an iframe hosted by the processor, the application's server never receives card data, and card numbers are not stored anywhere in the application's infrastructure.
- Tokens (Stripe customer IDs, payment method IDs) are not cardholder data and are out of PCI scope. Store tokens, not card numbers.
- Logging is the most common accidental PCI scope expansion. Any log that contains a card number, even in an error message, puts that log storage system in scope.
- PCI DSS applies to service providers too. A SaaS product that stores or transmits payment data on behalf of its customers is a service provider with its own compliance obligations.
The core argument
PCI DSS compliance is not a single binary question but a scope question. The compliance burden scales with scope: SAQ A has 22 requirements and no in person assessment; SAQ D has 326 requirements and potentially requires a Qualified Security Assessor. The difference is entirely architectural: a payment integration that keeps card data completely within the processor's infrastructure is SAQ A territory; a payment integration where card data passes through the application's servers even briefly is SAQ D territory. The architecture decision that determines scope is made early and is expensive to change later.
The Stripe.js / Stripe Elements architecture is the standard modern approach for avoiding PCI scope expansion. Stripe provides a JavaScript library that renders an iframe hosted on Stripe's domain. The user types their card number into the Stripe iframe. Stripe tokenizes the card and returns a token to the application. The application never sees the card number; it sees only the token. From a PCI perspective, the application is not in contact with cardholder data at any point in this flow. Stripe's infrastructure is PCI compliant; the application's infrastructure inherits that compliance for the card data processing portion of the transaction.
The failure modes are subtle and expensive. An application that logs all API request bodies for debugging purposes will log the card tokenization request if the card number is included in that request. An application that stores the card data temporarily in a session or cache before forwarding it to Stripe has the card data in scope. An application that passes card numbers through a server side proxy "to have more control" over the user experience has expanded its PCI scope to include the proxy infrastructure. Each of these is an architectural mistake made for understandable reasons that creates significant compliance overhead.
Common mistakes
Building a custom payment form that submits card data to the application server. This is the most impactful scope mistake. Any server that receives a card number in any request is in scope. Switch to hosted fields or Stripe Elements where the card data is collected and tokenized by the processor's infrastructure.
Including request body logging without PCI data filtering. Application servers that log all request bodies will eventually log card data. Add PCI sensitive field filtering to the logging layer that redacts card numbers, CVVs, and full names when they appear in log content, regardless of which endpoint received them.
Treating PCI as a one time assessment. PCI compliance is ongoing. Systems change, new services are added, logging configurations change, and personnel change. An annual review of the cardholder data environment and scope is necessary to maintain compliance.
Not documenting the data flow. PCI assessors require a data flow diagram showing where cardholder data enters, moves through, and exits the environment. Applications without documented data flows need significant work before the assessment to produce one. Document the payment data flow when the integration is built, not when the auditor asks for it.
Assuming the payment processor is responsible for all PCI compliance. The payment processor is responsible for the data within their systems. The merchant or service provider is responsible for the data within their systems. Using Stripe does not make the application PCI compliant; it limits the PCI scope to the cardholder data environment that the application controls.
Where to start
Audit the current payment integration for cardholder data touches. Trace the path of a card number from when the user types it to when the charge is processed. Does it pass through the application server? Is it stored anywhere, even temporarily? Is it included in any API request body that might be logged?
Implement hosted payment fields if not already in use. Stripe Elements, Braintree Hosted Fields, and Adyen Web Components all provide iframes hosted by the processor that remove card data from the application's scope. The implementation change is typically a front end change (replace a custom form with the processor's component library).
Implement PCI sensitive field filtering in logging. Add a logging middleware that detects and redacts patterns matching card numbers (16 digit sequences with specific format), CVVs (3 to 4 digit sequences in specific contexts), and full names in payment contexts. This is a defensive measure that prevents accidental scope expansion from debugging code.
FAQ
Frequently asked
- What determines PCI DSS compliance scope for a SaaS product?
- What is SAQ A and why does it matter?
- What is tokenization and how does it reduce PCI scope?
- What are the common PCI scope mistakes in SaaS applications?
- When does a SaaS product need a formal PCI audit versus self assessment?
Author
A note from Yashveer Singh
This was written by me, Yashveer Singh. The reason I write at this length and this depth is that the alternative is generic SEO content, and I am not interested in being one more of those. If you found this post useful, that is by design. If you want to talk about the project you are facing, the work happens through one channel: send a message via Instagram, and I will get back to you with a real answer, not a templated reply.