Magecart is the name given to attacks that inject JavaScript into an online store's checkout page to copy the card details shoppers type, then send them to the attacker. The name comes from the first targets, Magento shopping carts, but the same technique now hits WooCommerce, other platforms and any site that takes payments in the browser. The store keeps working, orders go through, and nobody notices until cards are misused. This guide explains how skimmers get into a WooCommerce store, where they hide, how to detect them, and what to do if you find one. It is part of WooCommerce security, which covers the rest of the store.
Quick answer
- Magecart = a card skimmer in JavaScript. It reads the payment form or shows a fake one, and sends the data to a domain that looks harmless.
- It gets in through a vulnerable plugin, a stolen admin login, or a compromised third-party script the checkout loads.
- On WooCommerce it hides in the database (options, widgets, posts), in fake or modified plugins, and in theme files, and it often runs only on the checkout.
- Hosted payment fields help but do not protect you fully. A skimmer can put a fake card form over them.
- Detect it by listing every script the checkout loads, as a logged-out shopper, and comparing with what should be there. A Content Security Policy with reporting does this for you continuously.
- If you find one, switch payments to a hosted payment page, preserve evidence, clean the site, and tell your payment provider.
What is a Magecart attack?
"Magecart" started as the name researchers gave to groups that skimmed cards from Magento stores. It became the general term for web skimming, sometimes called formjacking or e-skimming. RiskIQ's researchers tied Magecart to the 2018 breach of British Airways, where modified JavaScript on the booking site copied customers' payment details; the UK Information Commissioner's Office later fined the airline £20 million.
Most victims are not airlines but small stores. A skimmer on a shop with a few orders a day collects fewer cards, but small stores are easier to break into and slower to notice.
The attack is quiet by design. The shopper sees a normal checkout, the payment succeeds, and the order arrives. The only difference is one extra request in the background carrying the card number, expiry date, CVC, name and address to the attacker's server. Nothing breaks, so nothing prompts an investigation, until customers report fraud and the card networks trace the common point of purchase back to your store.
How skimmers work on a WooCommerce checkout
A skimmer has three parts: a trigger, a capture and an exfiltration.
The trigger. The code checks the URL and runs only on the checkout, often only when the page contains payment fields. Many versions also skip visitors with a WordPress login cookie, so the store owner never loads it.
The capture. Either it listens to the card fields and copies each keystroke, or it hides the real payment fields and shows its own form. Card fields in the provider's iframes cannot be read by a script on your page, so skimmers on stores with hosted fields use the fake-form trick: they show their own card form, collect the data, and then display an error or hand over to the real form so the shopper tries again.
The exfiltration. The data is encoded, often several times, and sent to a domain chosen to look legitimate, such as a lookalike of a CDN, an analytics service or your payment provider. It may go as an image request, a fetch call or a WebSocket, sometimes only when the shopper clicks "Place order".
How skimmers get into WooCommerce
- A vulnerable plugin or theme. An unpatched extension lets an attacker write to the database or upload a file. This is the most common way in.
- A stolen admin login. Anyone with administrator access can add a script through a widget, a custom HTML block, a header-and-footer plugin or a new plugin.
- A fake plugin. Attackers upload a plugin with a harmless-sounding name that contains the skimmer and sometimes hides itself from the plugin list.
- Modified legitimate files. Security researchers at Sucuri have documented skimmers added to a payment gateway plugin's own files and to theme
functions.phpfiles. - A compromised third party. A tag manager container, a chat widget, a review badge or a JavaScript library served from someone else's server can be changed at the source. Every store that loads it on the checkout then runs the new code.
Where it hides
Sucuri reported in January 2025 on a WordPress skimmer stored in the database, in the wp_options table under the widget_block option, which rendered as a script on checkout pages and passed file-based malware scans. That is typical: the database is the favourite hiding place because scanners and developers look at files first.
Common places to look:
| Place | What to search |
|---|---|
wp_options | widget_% options, header/footer script settings, unknown options holding <script |
wp_posts | The checkout page's content, reusable blocks, custom HTML blocks |
wp-content/plugins/ | Plugins you did not install; recently changed files in the gateway plugin |
wp-content/mu-plugins/ | Anything; must-use plugins run without appearing under Plugins |
| The theme | functions.php, header.php, footer.php and the checkout templates under woocommerce/ |
| Tag manager | New tags or custom HTML in your Google Tag Manager container |
How to detect a skimmer from the outside
The checkout only renders with something in the basket, so no scanner that fetches a single URL sees it. Check it yourself, the way a shopper does:
- Open a private browser window, not logged in to WordPress.
- Add a product to the basket and go to the checkout.
- Open the developer tools (F12), then the Network tab, and reload the page. Filter by "JS" and then by "Fetch/XHR".
- List every domain that serves a script or receives a request. Your own domain, your payment provider and a few services you know should be the only ones.
- Type test data into the form and click Place order with an invalid test card, watching for requests to domains you do not recognise.
- Repeat on a phone, or with the browser's device emulation, because some skimmers target mobile only.
Keep the list of expected domains in a document and repeat the test monthly and after every plugin change. A new domain on the checkout is a question you need an answer to.
Let the browser report it: a Content Security Policy
A Content Security Policy (CSP) tells the browser which sources may run scripts and receive data on a page. With a policy that allows only your domain and your payment provider, a skimmer that loads from or sends to another domain is blocked, and with a report endpoint you learn about it.
Start in report-only mode on the checkout so nothing breaks:
Content-Security-Policy-Report-Only: script-src 'self' https://js.stripe.com; connect-src 'self' https://api.stripe.com; frame-src https://js.stripe.com; report-uri https://example.com/csp-reportReplace Stripe's hosts with your provider's documented ones, add the services your checkout really needs, and watch the reports for a few weeks before switching to an enforcing policy. Rolling out a Content Security Policy walks through the steps, and subresource integrity for third-party scripts shows how to pin the exact version of a static third-party file so a change at the source is refused.
A CSP is not a complete defence: a skimmer injected inline or through an allowed domain can get past it, and WordPress sites often need 'unsafe-inline' for scripts. It does make the attack harder and the detection faster.
What getReport can check
getReport fetches the URL you give it, as a logged-out visitor, without adding anything to a basket. It cannot see a checkout that only renders with a cart, and it does not look for skimmers. It does show the defences and the risks around them:
A full report on a product page lists the third-party scripts the page loads, which is a good start for your list of expected domains:
The WordPress security scan flags the usual ways in, an outdated WordPress and plugins closed on wordpress.org:
How to find a skimmer from the inside
With WP-CLI on the server, search the database and files for scripts and the domains you saw in the Network tab:
# Scripts stored in options and posts (legitimate ones will show up too; review each)
wp db query "SELECT option_name FROM $(wp db prefix)options WHERE option_value LIKE '%<script%'"
wp db search "<script" --all-tables --stats
# A suspicious domain you saw in the Network tab
wp db search "suspicious-cdn.example" --all-tables
grep -rl "suspicious-cdn.example" wp-content/ wp-config.php
# Core and plugins against official checksums; changed gateway files are a red flag
wp core verify-checksums
wp plugin verify-checksums --all
# Recently changed PHP and JS files
find wp-content -type f \( -name "*.php" -o -name "*.js" \) -mtime -30 -lsPremium plugins cannot be verified against wordpress.org; compare them with a fresh download from the vendor. Look at the administrator list too: a skimmer added through the admin usually comes with a new administrator account.
What to do if you find a skimmer
- Stop the capture. Switch the gateway to its hosted payment page, or put the store in maintenance, until the site is clean.
- Preserve evidence. Copy the database and files, and the access logs, before you change anything. Note the dates you can find.
- Tell your payment provider straight away. They and the card networks decide what happens next and may require a forensic investigation.
- Clean the site as for any hack: remove the skimmer and the backdoor, reinstall WordPress, WooCommerce, the gateway and every plugin from clean sources, and review every administrator. Recovering a hacked WordPress site has the full order.
- Rotate every secret: WordPress passwords and salts, hosting and database passwords, payment gateway API keys and webhook secrets, WooCommerce REST API keys.
- Meet your data-protection duties. Stolen card and address data is a personal data breach. In the EU and UK, the GDPR requires notifying the supervisory authority within 72 hours of becoming aware of a breach unless it is unlikely to result in a risk to people; affected customers may also need to be told. Get advice early.
How to prevent Magecart attacks on WooCommerce
- Update WooCommerce, the gateway and every extension promptly, and remove what you do not use.
- Two-factor login for every administrator and shop manager. Many skimmers are added by someone who logged in.
- Load as little as possible on the checkout. No chat, A/B testing or heatmap scripts there, and dequeue plugin scripts that are not needed.
- Use hosted payment fields or a hosted payment page, never a form that posts card numbers to your server.
- Monitor the checkout's scripts: a CSP with reporting, a monthly manual check, and file-integrity alerts on the server.
- Keep an inventory. PCI DSS v4.0 requirements 6.4.3 and 11.6.1, mandatory since 31 March 2025 for merchants they apply to, ask for an inventory of payment-page scripts with a reason for each, and a mechanism to detect unauthorised changes to the page. Since the PCI Security Standards Council's January 2025 update, merchants filing SAQ A instead confirm their site is not susceptible to script attacks. Either way, the habits above are how you meet it.
Questions people ask
What does Magecart mean?
Magecart is the collective name for groups and attacks that skim payment card data by injecting JavaScript into checkout pages. The name combines Magento, the shop platform the first attacks targeted, and cart. Today it covers web skimming on any platform, including WooCommerce, Shopify apps and custom stores, and is also called formjacking or e-skimming.
Can Magecart skim cards if my payment fields are in an iframe?
It cannot read the fields inside the provider's iframe, but it can still steal cards. Skimmers on stores with hosted fields hide the real iframe and show their own fake card form, collect what the shopper types, then show an error so the shopper pays again through the real form. A redirect to a hosted payment page is harder to attack, but the redirect link on your site can be changed too.
How long do card skimmers stay undetected?
Often weeks or months, because nothing breaks. Orders and payments work normally, and skimmers usually hide from logged-in administrators and fire only on the checkout. Stores typically find out when their payment provider or bank reports fraud traced back to them. A Content Security Policy with reporting and a monthly check of the checkout's scripts shorten that window from months to days.
Does a malware scanner detect Magecart skimmers?
Sometimes. File scanners catch known skimmer code in plugin and theme files, but many skimmers live in the database, in widget or option values, or load from a third-party domain, and pass file scans. Combine a server-side scan with a database search for scripts and a manual check of every domain the checkout contacts in the browser's Network tab.
What should I do if customers report card fraud after buying from my store?
Treat it as a possible skimmer until proven otherwise. Check the checkout's scripts in a private window, search the database and files for unknown scripts, and tell your payment provider immediately. If you find a skimmer, switch to a hosted payment page, preserve evidence, clean the site, rotate every key, and follow your data-protection duties for notifying the authorities and customers.