PCI DSS Requirement 11.6.1: How to Set Up Tamper Detection on Your Payment Page
If Requirement 6.4.3 tells you to keep an inventory of every script on your payment page, Requirement 11.6.1 tells you to notice when that inventory changes. They’re a pair. You can’t satisfy one without the other.
This article is the practical companion: what 11.6.1 expects, how often, and exactly what counts as a “change” you have to alert on.
What 11.6.1 actually says
The control language, in plain English: deploy a mechanism that detects unauthorized modifications to HTTP headers and the contents of payment pages received by the consumer browser. Run it at least weekly. Alert someone when modifications happen.
Three pieces:
- Detect. You need a system that compares “what’s there now” against “what should be there.”
- Modifications. Both the HTTP headers (think CSP, security headers) and the script content of the page itself.
- Alert. Not just log it. Tell someone it happened.
The “weekly” cadence is the bare minimum. Most merchants run it more often — daily or hourly — because skimmers can monetize for days before the next weekly scan catches them.
How it pairs with 6.4.3
The two rules together form a closed loop:
- 6.4.3 establishes the authorized baseline. “Here’s the inventory, here’s the justification, here’s the integrity hash for each script.”
- 11.6.1 monitors the live page against that baseline. “Did anything change? If yes, alert.”
- The merchant investigates the alert, decides whether the change is legitimate, and either re-authorizes (updating the 6.4.3 inventory) or remediates.
You can’t have one without the other and call yourself compliant. An inventory you never check against reality is paperwork. A monitor with no baseline tells you nothing useful.
When this took effect
Like 6.4.3, Requirement 11.6.1 was introduced in PCI DSS v4.0 (March 2022) and became mandatory and assessable on March 31, 2025.
Pre-2025 you could attest to it as “best effort” without a real implementation. Post-2025 your assessor expects to see weekly scan reports for the period being attested.
What “modification” actually means
This is where merchants stumble. The rule is broader than it sounds.
Script content changing — your analytics.js was 12,847 bytes last week and is 12,891 bytes this week. The hash changed. That’s a modification.
A new script appearing — last week you had 23 scripts on your checkout. This week you have 24. Whatever the new one is, that’s a modification.
A script disappearing — last week you had 23 scripts. This week you have 22. That’s also a modification (the 11.6.1 control text says “modifications,” which the assessor reads broadly).
HTTP headers changing — your CSP script-src allowlist used to include js.stripe.com and now includes js.stripe.com and widget.someothervendor.com. That’s a modification.
Inline script content changing — a <script> block in your template went from 50 lines to 60 lines. Modification.
A script’s source URL changing — the same script that used to load from cdn.example.com/foo-1.2.3.js now loads from cdn.example.com/foo-1.2.4.js. Modification.
The rule is intentionally broad because attackers are creative. A weekly scan that only alerts on “new domains in script-src” misses an attacker who compromises a script you already authorized.
What weekly automated detection looks like
The simplest implementation:
- Run a headless browser (Chrome via Playwright or Puppeteer, or our free scanner) against your checkout page.
- Capture every script’s URL and SHA-384 hash, every inline script’s content hash, every relevant HTTP header.
- Compare against last week’s snapshot.
- Alert on any difference.
- Store the snapshot as the new baseline once the change is reviewed and authorized.
The infrastructure is simple. The hard parts are:
- What channel does the alert go to? Email is fine for most SMBs. Slack/Teams works if you have one. PagerDuty is overkill for a small store.
- Who responds to alerts? The store owner if you’re solo. The marketing or ops manager if there’s a team. There has to be a named human.
- How do you decide whether a change is legitimate? This is the awkward part. Most legitimate changes come from one of: a vendor pushing an update, you installing a new plugin, a content team adding a tag. You need a way to ask “did one of us do this?” before assuming it’s hostile.
False positives are the failure mode
The single biggest reason 11.6.1 implementations fail in practice is alert fatigue. If your monitor cries wolf every Tuesday because Google Tag Manager pushed a 50-byte change, the alert gets muted within a month.
Three patterns to reduce noise:
- Pin scripts to versioned URLs where possible. A script loaded from
cdn.example.com/foo-1.2.3/foo.min.jsshouldn’t change content. If it does, that’s genuine cause for alarm. A script loaded fromcdn.example.com/foo/latest.jswill change every time the vendor pushes; treat hash changes there as informational, not alerts. - Have a known-changes list. “GTM pushes daily, treat hash changes there as expected.” This isn’t a free pass — you still want to know that it changed — but the alert is informational, not actionable.
- Alert on high-risk changes more loudly. A new domain appearing in
script-srcis a louder alert than a hash change in your already-authorized analytics. A new inline<script>block on your checkout is a much louder alert than a hash change in a file you already trust.
A good monitoring setup grades the alert by how surprising the change is.
What auditors look for
When a QSA reviews your 11.6.1 evidence, they’re checking three things:
- The mechanism exists and runs on a schedule. Show them the cron job, the GitHub Action, the SaaS dashboard — whatever proves it’s real.
- The mechanism produces output. A folder of weekly scan reports for the past three months. Each scan dated, each showing what was found.
- Changes were investigated. When the scan flagged a difference, evidence that someone looked at it and either signed off (re-authorized) or remediated. A short note attached to each “change confirmed legitimate” entry is enough.
The third one is what catches merchants who set up automated scans but never read the output. The auditor wants to see that the loop closed — that an alert led to a decision.
Common implementation mistakes
Scanning the wrong page. 11.6.1 applies to the page where the customer enters their card. Not your homepage, not your cart page (unless your cart has the card form). Make sure your scanner is hitting the actual checkout URL, including any URL parameters that change which scripts get loaded.
Scanning logged-out only. A lot of checkout pages render different scripts for logged-in customers. If your scan only hits the page as an anonymous visitor, you’re not seeing what your real customers see. If your checkout has logged-in vs anonymous variants, scan both.
Scanning from one geography. Some merchants serve different scripts based on customer location (GDPR consent walls add cookie-management scripts in EU traffic; A/B tests vary by region). If you’re geographically split, your scan needs to reflect at least the major regions.
Capturing the network response only. A skimmer that’s injected into the DOM after page load via a tag manager won’t show up in network captures. You need to inspect the rendered DOM after the page has stabilized — which is why headless-browser-based scanners are more reliable than HTTP fetch + regex.
Storing the baseline in the same place as the live site. If an attacker compromises your WordPress install and edits the baseline file too, your monitor will compare “current state” against “current state” and find no difference. The baseline has to live somewhere the live site can’t reach.
What this looks like with CheckoutProof
The free scanner does the inventory part — it’ll tell you what’s on your checkout right now. The paid product runs the scan on a weekly schedule, stores the baseline outside your infrastructure, alerts you to changes via email or Slack, and produces the audit-evidence pack QSAs ask for.
You don’t have to use ours. You do have to satisfy 11.6.1 somehow before your next attestation. The cheapest way to fail an audit is to have done 6.4.3 perfectly and ignored 11.6.1.
Run a free scan on your checkout right now and lock in your baseline.
Run a free PCI 6.4.3 scan of your checkout page. Get the script inventory and a one-page PDF report. Try it now →