Django PCI DSS Checklist for Apps That Take Payments

A PCI DSS checklist for Django apps accepting card payments: minimize scope with hosted payment fields or redirects, never store card data, secure the pages that load payment scripts, protect against script tampering, manage access, logging, vulnerability scanning, and SAQ evidence.

Problem statement

Your Django app takes card payments, and the payment provider asks you to complete a PCI DSS Self-Assessment Questionnaire (SAQ). Which requirements apply depends almost entirely on whether card data ever touches your servers. Using hosted payment pages or embedded fields from Stripe, Adyen, Braintree, or similar keeps you in the smallest scope, but PCI DSS 4.0 added requirements for the pages that load payment scripts. This checklist helps engineering teams keep scope small and meet the remaining controls.

PCI scope for DjangoPayment UIhosted or iframeCard datanever on your serversPayment pagescript integrityEvidenceSAQ, scans, logsKeep card data on the provider’s side so your scope stays small.
  1. Use hosted checkout or provider iframes/elements so card numbers go straight to the provider (SAQ A or A-EP scope).
  2. Never log, store, or transmit card numbers, CVVs, or track data through Django; scrub them from logs and error reports.
  3. Protect payment pages: a strict Content Security Policy, an inventory of scripts, and tamper detection (PCI DSS 4.0 requirements 6.4.3 and 11.6.1).
  4. Secure the environment: patched dependencies, MFA for admin and infrastructure access, TLS everywhere, and logging of administrative actions.
  5. Run quarterly external vulnerability scans if your SAQ requires them, and keep evidence for each answer.

Checklist

Scope reduction

  • Card data entered only in provider-hosted pages or iframes (Stripe Checkout or Elements, Adyen Drop-in, Braintree Hosted Fields).
  • No card numbers in Django forms, models, logs, or database, ever; tokens or payment method IDs only.
  • Webhooks from the provider verified by signature; webhook payloads contain no full card data.
  • SAQ type confirmed with the payment provider or acquirer (A for fully hosted redirects or iframes, A-EP if your page controls the payment form's surroundings).

Payment page security (PCI DSS 4.0)

  • Inventory of every script loaded on payment pages, with justification for each.
  • Content Security Policy restricting scripts to your domain and the provider, with violation reporting.
  • Subresource Integrity or equivalent controls for third-party scripts where possible.
  • Change and tamper detection for payment page headers and scripts (monitoring service or scheduled checks).
integration and typical SAQCard data touches Django?Typical SAQRedirect to hosted checkoutnoAProvider iframe fieldsnoAJS-built form posting to providerno, but page controls formA-EPCard data via Django✕yes✕D, full scopeThe integration choice decides most of your PCI workloaddjango-deployment.com
Confirm your SAQ type with your acquirer; this table is a guide, not a ruling.

Access control and authentication

  • Unique accounts and MFA for Django admin, cloud consoles, CI/CD, and servers.
  • Least-privilege roles; payment-related admin actions (refunds, payouts) limited to specific staff.
  • Strong password policy and lockout (django-axes or similar) for staff accounts.
  • Prompt removal of access for departing staff, with periodic reviews.

Secure development and patching

  • Dependencies pinned and scanned (pip-audit, Dependabot); critical patches applied within defined timelines.
  • Code review for changes to payment flows and templates of payment pages.
  • DEBUG = False, security headers, and check --deploy clean in production.
  • Secrets (provider API keys, webhook secrets) in a secrets manager, rotated after staff changes or leaks.

Logging, monitoring, and testing

  • Logs of admin actions, authentication events, and payment-related operations, retained per policy (at least a year, with recent months readily available).
  • Alerts on suspicious activity: many failed payments, refund spikes, admin logins from new locations.
  • Quarterly external vulnerability scans by an approved scanning vendor if your SAQ requires them.
  • Annual review of the SAQ and evidence collection.
yearly cycle1Confirm SAQ typewith acquirer2Inventory payment scriptsCSP, SRI3Collect access and patch recordsMFA, reviews4Run required scansASV, quarterly5Complete and sign SAQstore evidenceEvidence gathered during the year makes the SAQ a formalitydjango-deployment.com
Requirements change between PCI DSS versions; check the current one.

Explanation

PCI DSS protects cardholder data. Its scope covers every system that stores, processes, or transmits that data, plus systems that can affect its security. Hosted payment fields and redirects keep card numbers entirely within the provider's environment, so your Django app never handles them and only a small subset of requirements applies. PCI DSS 4.0 recognized that attackers inject skimming scripts into payment pages, so even SAQ A merchants must control and monitor the scripts on pages that host payment forms.

Edge cases / notes

  • Phone orders. Staff typing card numbers into your admin brings systems into scope; use the provider's virtual terminal instead.
  • Saved cards. Store provider tokens or payment method IDs, never card numbers or CVVs.
  • Logs and Sentry. Make sure request bodies and headers on payment-adjacent endpoints are scrubbed.

Next steps

FAQ

Do I need PCI compliance if I use Stripe?

Yes, but usually at the smallest scope (SAQ A) when you use Stripe Checkout or Elements and never handle card data.

Can I store card numbers in my Django database?

Avoid it. Store provider tokens instead; storing card data puts your whole environment in full PCI scope.

What did PCI DSS 4.0 change for small merchants?

It added requirements to manage and monitor scripts on payment pages, even for hosted or iframe integrations.

Who decides my SAQ type?

Your acquirer or payment provider confirms it based on your integration.

Keep going