Build-an-X for PCI DSS v4.0 scope verification - cardholder data environment (CDE) boundary tests, segmentation tests (PCI Req 1), prohibited-data-storage assertions per Req 3 (no full track data, no CVV/CAV2/CVC2/CID, no PIN/PIN block post-authorization), key-management tests per Req 3.6, encryption-of-transmissions per Req 4; includes the scope catalog (SAQ A / A-EP / D levels, PAN-storage rules, hosted-fields / tokenization scope-reduction patterns) in references/pci-scope.md. Use when authoring PCI DSS scope-reduction + control tests for any system handling payment-card data, or when determining a payment integration's SAQ level.
72
90%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
High
Do not use without reviewing
Pure-reference catalog of PCI DSS v4.0 scope reduction techniques + the testable scope boundaries. This is the catalog of WHY the boundary matters and what it makes testable; the SKILL.md steps are the workflow that verifies a given integration against it.
Scope reduction is the dominant strategy: keep card data off your systems entirely, so PCI compliance becomes minimal SAQ A instead of full SAQ D.
| SAQ | Description | Scope |
|---|---|---|
| A | Card-not-present, fully outsourced (hosted gateway pages, iFrame redirects, Stripe Elements) | Smallest - your servers never see PAN |
| A-EP | Hosted-form-with-merchant-customisation (e.g., your domain shows the form but iframe is the gateway's) | Slightly larger; some elements visible to your server |
| D | All merchants not covered by A-C; full PCI DSS | Largest - for cases where you must handle PAN |
Choose A when feasible: PAN never touches your servers because the customer inputs it directly into a gateway-hosted iframe / element.
Per PCI DSS v4.0 §3.4: prohibited storage of:
Allowed:
pm_*)Tests for storage (PostgreSQL ~ regex operator):
-- Detect prohibited PAN patterns in any string column
SELECT * FROM <any_table>
WHERE column ~ '^[0-9]{13,19}$'
OR column ~ '^4[0-9]{15}$'
OR column ~ '^5[1-5][0-9]{14}$'
LIMIT 10;
-- Expect: 0 rowsPer stripe.com/docs/payments/payment-element, docs.adyen.com/payment-methods/cards/web-drop-in, developer.paypal.com/braintree/docs/start/hosted-fields:
<!-- Stripe Element -->
<form>
<div id="payment-element"></div> <!-- iframe; PAN stays in Stripe's iframe -->
<button>Pay</button>
</form>PAN never reaches your JS or backend. The Element sends to Stripe directly; your server gets a token.
Customer redirects to gateway-hosted page; pays; redirects back with a token / transaction ID.
PCI-friendly because PAN never on your domain. UX-tradeoff: slower, less branded.
Backend-to-backend: customer submits PAN to gateway directly (via JS); gateway returns token; your code uses token.
Variants per gateway: Stripe setupIntent for saved cards;
Adyen paymentMethods.storeDetails; PayPal Vault.
If you must touch PAN, isolate it in a separate network with strict ingress / egress + monitoring. Reduces scope of the broader IT environment.
| Behaviour | Test |
|---|---|
| No 16-digit numbers in DB | SQL regex against all string columns |
| No CVV / CVC stored | Search code for cvc, cvv, cardholderVerification |
| Hosted fields render without exposing PAN to your JS | Browser DevTools Network tab - no PAN in requests to your origin |
| Webhooks contain tokens not PAN | Parse webhook payloads; assert no 16-digit numbers |
| Log scrubbing | Test logs for PAN patterns; should be redacted |
| Backup snapshots PAN-free | Same regex against backup files |
| Egress firewall blocks card-network IPs | Network test |
The SKILL.md steps run these adversarially; this catalog provides the rationale.
| Anti-pattern | Why it fails | Fix |
|---|---|---|
| Log entire payment request body | PAN in logs | Scrub at log emit |
| Stage card-collection on your own page | Cards now in your domain → SAQ D | Use hosted fields |
| Send PAN to backend then forward to gateway | Server now PCI-scope | Direct JS-to-gateway |
| Store PAN encrypted "just in case" | Key management is half of PCI DSS | Use tokens |
| Test PAN in fixtures | Real PAN in commits | Use only platform-provided test PANs |
| Capture CVV server-side | PCI DSS v4.0 §3.2.1: prohibited post-auth | Don't capture or capture in scoped iframe |
| Skip scope-checker in CI | Drift over time | Periodic scope audit |