# How to catch a Magecart-style attack with CSP monitoring

> A web skimmer betrays itself twice: when the malicious script loads on your checkout, and when it POSTs card data to an attacker origin. How CSP monitoring catches both signals from real visitors within minutes, and how an enforced connect-src can block the exfiltration outright.

- Canonical: https://info.centralcsp.com/articles/catch-magecart-attack-csp/
- Published: 2026-08-09
- Language: en
- Publisher: CentralCSP (https://centralcsp.com)

A Magecart-style skimmer gives itself away twice. First when it loads: a script from an origin you have never used, a new URL on a known origin, or a changed integrity hash on a script that was already there. Second when it exfiltrates: a POST to an origin your `connect-src` never allowed. CSP monitoring watches both signals from real visitors' browsers, so detection takes minutes instead of the weeks these attacks usually run. And if `connect-src` is enforced and tight, the browser refuses the exfiltration request outright.

Below, the anatomy of the attack, then how each signal shows up in practice.

## How a Magecart attack actually works

The playbook has been stable for a decade. The attacker gets JavaScript onto the pages where card numbers are typed, by one of two routes: compromise a third-party script the checkout already loads (a chat widget, a tag manager payload, an analytics bundle served from a CDN they managed to poison), or inject a new snippet directly, often through a CMS or plugin vulnerability.

The skimmer then does very little, deliberately. It attaches listeners to the payment form fields, collects card number, expiry, CVV and billing details as the customer types, and sends them to a server the attacker controls. The exfiltration endpoint is usually a look-alike domain nobody would flag at a glance. Checkout completes normally. Conversion stays flat. There is no error to investigate.

That silence is the whole problem. British Airways' 2018 skimmer ran for about two weeks and touched hundreds of thousands of cards. Plenty of smaller shops host one for months. Since nothing breaks, the only thing left to catch is change itself: a script that was not there last week, a connection to a domain nobody recognizes.

## The two signals that betray a skimmer

CSP gives you exactly two, and conveniently they bracket the attack.

The first is the load. Whatever route the skimmer took in, a real customer's browser ends up executing script content that was not there before. From CSP's point of view that surfaces as one of three events: a script from a brand-new origin, a new script URL on an origin you already use, or hash drift, meaning the content at an existing URL no longer matches its known SHA-256 hash. Hash drift is the one a URL allowlist can never see, and it is precisely the compromised-third-party case.

The second is the connection. Stolen data has to leave the page. A skimmer that POSTs via `fetch`, XHR or `sendBeacon` to `attacker-origin.example` trips `connect-src`. One that rewrites the form target trips `form-action`. This signal is the stronger of the two, because it fires even when the load signal did not: the browser itself reports the attempt, from the customer's machine, at the moment it happens.

In report-only mode both signals arrive as violation reports. In enforcing mode the second one gets better: the browser blocks the request, the card data stays on the page, and the report becomes your incident record rather than your breach notification.

## What detection looks like in practice

[CentralCSP's Script Inventory](https://centralcsp.com/en/platform/supply-chain/) covers the load side. It is built from CSP hash reporting (`report-sha256` and its variants under the script directives), so every script executed by a real visitor lands in the inventory with its origin, full URL and integrity hash. No agent on the checkout, no crawler. That matters: fingerprinting headless browsers and serving clean content to scanners is standard skimmer behavior now, and a signal sourced from real customer traffic is immune to it. The mechanics are in [our article on detecting third-party script changes](/articles/detect-third-party-script-changes/).

On top of the inventory, [alert rules](https://centralcsp.com/en/platform/alerting/) fire into Slack, Microsoft Teams, Google Chat, Telegram, email or HMAC-signed HTTPS webhooks on ingest of the first report. The site-wide new script origin rule (Business, €129.99/mo, unlimited alerts) catches the first of the three load signals. The other two, a new URL on a known origin and a changed hash, are caught on the pages you declared as payment pages (`/checkout/*`, the pages hosting your payment iframe) by the unjustified-script rule of the PCI DSS module on Scale (€349.99/mo): anything there that nobody has justified goes to a pending queue and pages your on-call while the skimmer is hours old, not weeks. The tuning details, including how to keep your own deploys from paging anyone, are in [our guide to checkout page script alerts](/articles/checkout-page-new-script-alerts/).

The connection side is a policy decision more than a tooling one. Write `connect-src` to list only the origins your checkout genuinely talks to (your API, your PSP, your analytics endpoint) and enforce it. It is usually a short list, which is what makes this directive so effective on payment pages. Every exfiltration attempt then shows up in your violation stream as a `connect-src` block against an origin you have never seen.

## What CSP monitoring cannot see

Being honest about the boundary: CSP observes loads and connections. It does not observe behavior. It cannot tell you that an allowed script started reading form fields it never touched before.

The hard case is malicious code shipped inside a script you already allowed, at its usual URL, where you authorized that exact hash, perhaps because the vendor was compromised before you ever inventoried them. Hash monitoring has nothing to flag: from its perspective, nothing changed. Two things cover that gap. The enforced `connect-src` stops the stolen data at the border regardless of which script tried to send it. And a script authorization workflow forces a human to justify each script before it joins the allowed set, which shrinks the population of scripts that could carry the payload in the first place.

Neither is optional if the page takes card numbers. The load signal without the connection signal misses the poisoned insider. The connection signal without the load signal tells you about the theft attempt but not which script to pull.

## Why PCI DSS wrote this into the standard

Requirements 6.4.3 and 11.6.1 of PCI DSS v4 exist because of exactly this attack, and they have been mandatory in assessments since April 1, 2025. 6.4.3 is the load side made formal: an inventory of every script on payment pages, each one authorized with a written business justification. 11.6.1 is the change side: a tamper-detection mechanism evaluating the page as the consumer's browser receives it, at least every seven days. Continuous browser-sourced monitoring satisfies the mechanism and generates the evidence as a by-product. On CentralCSP the assessor-facing tooling (justification workflow, per-page inventory, dated change timeline, CSV and PDF export) sits on Scale plans (€349.99/mo) and up. The full breakdown is in [our analysis of 6.4.3 and 11.6.1](/articles/pci-dss-6-4-3-and-11-6-1-payment-page-requirements/).

The short version: a skimmer must load and it must exfiltrate. Watch both from the browser's side, enforce the connection policy, and an attack designed to run silently for weeks instead produces a Slack message in minutes and, on a well-configured page, steals nothing at all. The wider checkout picture, security headers included, is in [CSP monitoring for e-commerce](/articles/csp-monitoring-for-ecommerce/).

## Frequently asked questions

### How do Magecart attacks work?

An attacker gets JavaScript onto your checkout page, either by compromising a third-party script you already load (a chat widget, an analytics tag) or by injecting a new snippet. The script reads card number, expiry and CVV as the customer types them, then quietly POSTs the data to a server the attacker controls. Nothing breaks, checkout still works, and the skimmer typically runs for weeks before anyone notices.

### Can a Content Security Policy prevent card skimming?

An enforced CSP with a tight connect-src and form-action can block the exfiltration itself: the browser refuses to send data to any origin the policy does not list, so even a skimmer that managed to load cannot phone home. In report-only mode CSP does not block anything, but every violation still reaches your reporting endpoint, which turns the attack into a detection signal within minutes.

### Can a skimmer evade CSP-based detection?

Partially. CSP observes which scripts load and where the page connects, not what JavaScript does internally. If malicious code ships inside a script you already allowed, at its usual URL, and you authorized that exact hash, hash monitoring has nothing new to flag. That gap is why the exfiltration side matters: the stolen data still has to leave the page, and a tight enforced connect-src stops it at the door.

### Does CSP monitoring satisfy PCI DSS 6.4.3 and 11.6.1?

Those two requirements were written in response to Magecart: 6.4.3 demands an authorized, justified inventory of every script on payment pages, and 11.6.1 demands tamper detection at least every seven days. Browser-sourced script inventory and continuous change alerts map onto both. On CentralCSP, the full evidence tooling (justification workflow, exportable change timelines) is on Scale plans (€349.99/month) and up.
