Magecart: A UK Merchant’s 30-Day Defence Plan

Magecart: A UK Merchant's 30-Day Defence Plan

Magecart is the name given to a technique for stealing card details from the browser at the moment a customer pays. It is not a group. It is not a product. Understanding that distinction matters, because the defences that actually work are structural, and they do not care which crew wrote the code that ended up on your checkout.

What follows is a sequenced plan, not a list of best practices. Four weeks, in order, with the cheap work first. It assumes you run a live checkout and that PCI DSS 4.0 requirements 6.4.3 and 11.6.1 already apply to you, because they became mandatory on 31 March 2025.

What Magecart actually is, and why the name misleads people

Researchers coined the term by fusing Magento and shopping cart, back when the compromised stores they were seeing mostly ran Magento. The label stuck. The technique spread. Skimmers have since been found on Shopify stores, WooCommerce sites, hosted store platforms and bespoke checkouts written in-house.

So “we are not on Magento”is not a defence. The technique follows the card fields, not the content management system. Any page where a customer types a primary account number into an input you control is a target, and Magecart is best read as a label for a method rather than a gang. Treating it as a Magento problem is the single most common misreading, and it is how sites on other platforms end up with no script controls at all.

Every recorded incident maps to one of three routes in: a compromised third-party supplier whose script you load, injected first-party code in your own files or database, or a weakness in the platform or admin layer that let someone in to edit either.

While it runs, nothing looks broken. The form validates. The payment authorises. The confirmation email sends. A skimmer that breaks checkout gets removed within the hour, so skimmers do not break checkout. That quietness is the whole point.

The three routes in, read through real incidents

Third-party supplier

Ticketmaster UK disclosed in June 2018 that card details had been taken from its payment pages. The code was never in Ticketmaster’s repository. It arrived through a compromised chat widget supplied by a third party, loaded into the page as a script tag. The ICO fined Ticketmaster UK £1.25 million in November 2020 for failing to keep the data secure.

The same supply route hit hosted stores run for Warner Music Group. You inherit the security posture of every vendor whose JavaScript you execute on the payment page. All of them. Every deploy they make.

First-party injection

British Airways, between 21 August and 5 September 2018: a modified first-party script in the payment flow posted card data to a lookalike domain registered to resemble the airline’s own. The site behaved normally for the whole period. The ICO issued a £20 million fine in October 2020. Newegg was hit in the same window by the same pattern, with a handful of lines added to a legitimate file and an exfiltration host chosen to look like part of the brand.

Read plainly, that is a code integrity failure. Nobody noticed the file had changed.

Platform and admin weakness

In September 2020, security firm Sansec reported that around 2,000 Magento stores were compromised over a single weekend, the largest such campaign it had recorded. Almost all of them were running Magento 1, which reached end of support on 30 June 2020. VisionDirect, Macy’s and Claire’s each suffered incidents where the attacker got sufficient access to change what the browser received.

The pattern across these high-profile incidents and the routes they took tells you where week one goes: not on abstract threat modelling, but on finding out what your payment page loads and who can change it.

Week one: find out what your checkout is really loading

Build the inventory by hand first. Automation later. Open your live payment page in a browser, open DevTools, go to the Network tab, filter to JS, and reload with the cache disabled. Write down every domain, every file, the supplier who owns it and the business reason it is there.

Most operators find far more third-party scripts on a checkout they thought was lean than they expected. Expect at least one nobody can account for: a tag from a discontinued A/B test, an affiliate pixel from a partner you stopped working with, a heatmap tool added by a marketing agency three years ago. Remove those. A chat widget has no business on the page where card numbers are typed.

Then read the files. You are looking for a small number of tells:

  • Obfuscated blobs appended to the end of an otherwise readable legitimate file, often base64 or hex-escaped strings assembled at runtime.
  • Event listeners attached to inputs by name or attribute: cardnumber, cvv, expiry, or a blanket listener on the form’s submit event.
  • Outbound calls via fetch, XMLHttpRequest, navigator.sendBeacon or an image request with the payload in the query string, going to a host that is not in your inventory.

Check the entry points too, not just the output. Enumerate admin accounts and delete the dormant ones. Record extension and plugin versions against known vulnerabilities. List theme and template files modified in the last ninety days, and match each change to a deploy. There is a short set of checks you can run inside an hour if you need something before the full inventory is done.

One more thing, and it is the one operators resist. Detection usually arrives from outside. Card issuers and your acquirer can see a common point of purchase in fraud data long before any internal scan flags anything. If an acquirer calls about a CPP, treat it as a live incident. Do not argue with it.

Week two: take the card fields out of reach with hosted payment fields

The cheapest structural win is to stop hosting the card inputs yourself. With hosted payment fields, your provider serves the PAN, expiry and CVV inputs inside iframes on their own origin. Your JavaScript cannot read inside them. Neither can a skimmer running in your page, because the same-origin policy is enforced by the browser rather than by your code.

This is configuration work in most cases, not development work. That is precisely why it comes second and not last. Stripe Elements, Adyen Components, Worldpay and Checkout.com all offer this model, and moving card entry into provider-hosted fields also reduces the SAQ burden for most merchants, typically from SAQ A-EP towards SAQ A. Confirm the applicable level with your acquirer rather than assuming it.

A full redirect to the provider’s hosted page removes more scope again, at the cost of branding control and a conversion hit on mobile. Hosted fields keep the checkout looking like yours. Pick deliberately, and measure.

Now the caveat that generic guides skip. Hosted fields remove the card inputs from reach. They do not remove the attacker from your page. Name, address, email and phone still sit in your DOM, and that combination has resale value on its own. Worse, a script running in your page can draw a convincing fake card form directly over the legitimate iframe, capture the details, then hide the overlay and let the real payment proceed. Hosted fields plus CSP plus change detection is the combination. Hosted fields alone is not.

Week three: Content Security Policy and Subresource Integrity on a live payment page

Start in report-only. Send Content-Security-Policy-Report-Only with a script-src allowlist and a reporting endpoint, and leave it running for a fortnight. Read the reports. You will discover tags nobody in the business remembers commissioning, and that discovery on its own usually justifies the exercise. Enforcing straight to blocking mode is how teams take their own checkout down, generally late on a Friday.

A workable script-src for a checkout allowlists your own origin, your payment provider’s script host, and the small number of analytics domains you have decided are worth the risk. Inline script gets a nonce, regenerated per response. Do not include ‘unsafe-inline’ as a fallback: it undoes most of the benefit, and browsers that support nonces ignore it anyway when a nonce is present, so you end up with a policy that is either weak or inconsistent across your traffic. Add connect-src as well, or the skimmer keeps its exfiltration channel. A complete worked policy for a checkout page is a better starting point than copying a generic example.

Then pin what you cannot control. Subresource Integrity adds an integrity attribute carrying a SHA-384 hash of the file, plus crossorigin=”anonymous”. If the bytes change, the browser refuses to execute the script.

Here is the operational cost nobody mentions. Suppliers push updates without telling you. The hash stops matching, the browser blocks the file, and something on your checkout quietly stops working. The fix is not to abandon SRI. The fix is process: a change notification agreement with each supplier, self-hosting a reviewed copy where the licence allows it, a synthetic check that asserts each pinned script actually loaded, and an alert on blocked resources. Note also that pinning a loader does not pin what the loader fetches, which is why tag managers and chat widgets sit badly with hash-pinning third-party scripts. Remove them from the payment page instead.

Week four: satisfying PCI DSS 4.0 requirements 6.4.3 and 11.6.1 without buying a platform

Both requirements are now in force. They stopped being future-dated best practice on 31 March 2025, and the text is published openly by the PCI Security Standards Council.

Requirement 6.4.3 asks that every script loaded and executed in the consumer’s browser on the payment page is authorised, that its integrity is assured, and that a written justification exists for why it is necessary. Three things, and the third is where assessments fail.

Requirement 11.6.1 asks for a mechanism that detects and alerts on unauthorised modification to the HTTP headers and the payment page content as received by the consumer browser, evaluated at least weekly.

You do not need to buy a client-side security platform to meet either. A defensible minimum looks like this:

  1. A maintained inventory listing every script, its owner, its purpose and the person who authorised it, with a date.
  2. SRI hashes on every externally hosted script, recorded in the same inventory.
  3. CSP in enforce mode with a live reporting endpoint, and someone who reads the reports.
  4. A scheduled job that fetches the rendered payment page, hashes the script tags and the response headers, and diffs against the last known-good snapshot. Weekly at minimum. Daily costs nothing more.

Two failures come up repeatedly. The first is an inventory that lists domains with no written business justification, which satisfies nobody. The second is change detection that watches files on the server rather than what the browser receives, which misses injections from the database, the CDN, the tag manager and the supplier entirely. Assess the rendered page. If you want the requirement text unpacked line by line, there is a fuller treatment of what 6.4.3 and 11.6.1 ask of your payment page.

If you find a skimmer: the first 48 hours

Preserve before you clean. Copy the injected code verbatim, capture web server and application logs, and record file modification timestamps before you touch anything. Once you overwrite the file, the timeline is gone, and the timeline is what tells you the exposure window.

Then contain, in this order: remove the injection, rotate every administrative credential and API key, patch the entry point, and only then search for a second implant. Skimmer operators frequently leave two: one obvious, one in a database template or a cron job. Cleaning the first and declaring victory is common.

Notify your acquirer and payment provider immediately, because they will co-ordinate the card brands. Where personal data is affected you have 72 hours from becoming aware to notify the ICO, and the ICO’s breach reporting guidance sets out what the report must contain. Tell affected customers where the risk to them is high.

Re-infection is the normal outcome when the original route in is never identified. If you cannot say how they got in, assume they still can.

The short version

Week one, inventory what the payment page loads and who can change it. Week two, move the card fields into provider-hosted iframes. Week three, run CSP report-only for a fortnight, then enforce, and pin external scripts with SRI backed by a supplier change process. Week four, write the justifications and schedule a weekly diff of the rendered page. None of it requires a new vendor, and the deadline for 6.4.3 and 11.6.1 has already passed.

Frequently Asked Questions

Is Magecart one hacking group or many?

Many, and the name properly describes a method rather than an organisation. Researchers have tracked dozens of distinct clusters with different tooling, infrastructure and skill levels, some working at scale across thousands of sites and others targeting single merchants. Defending against “Magecart”means defending against the technique, because attribution changes nothing about what you need to do.

Does Magecart only affect Magento stores?

No. The name comes from Magento plus shopping cart, but skimmers have been found on Shopify, WooCommerce, hosted store platforms and bespoke checkouts. The technique targets the card input fields and the scripts loaded alongside them, not any particular platform.

Can a Content Security Policy stop a Magecart skimmer on its own?

A well-built policy stops a large class of attacks, specifically unauthorised scripts loading and unauthorised hosts receiving data. It does not stop an injection into a script you have already allowlisted, or a compromise of a supplier whose domain you trust. Pair it with hosted payment fields, SRI and change detection. If your acquirer later asks for proof that these controls are actually in place, our guide to proving SAQ A script eligibility sets out what counts as evidence.

What do PCI DSS 4.0 requirements 6.4.3 and 11.6.1 mean for my payment page?

6.4.3 requires every browser-executed script on the payment page to be authorised, integrity-assured and justified in writing. 11.6.1 requires a mechanism that detects unauthorised changes to the payment page content and HTTP headers as the browser receives them, checked at least weekly. Both have applied since 31 March 2025.

How do I know if my checkout has already been skimmed?

A working skimmer gives you no reason to look, so the honest answer is that you check deliberately or you hear it from someone else. Compare your live payment page scripts against a known-good inventory, look for listeners on card inputs and outbound calls to unfamiliar hosts, and treat any acquirer or issuer report of a common point of purchase as a live incident.