Skip to main content
Blog
Blog Attacks

Magecart Attacks Explained: How Web Skimming Works in the Browser

A plain explainer of how Magecart web skimming works: how the code gets in, how it reads your form fields, and how it exfiltrates card data unseen.

Jul 13, 2026 9 min read
Magecart Attacks Explained: How Web Skimming Works in the Browser

Magecart is web skimming that runs inside the browser. Malicious JavaScript lands on a checkout or login page, reads what the visitor types into the form, and sends a copy to a server the attacker controls. The legitimate payment still goes through, so from your servers it looks like a normal day of clean transactions. Everything looks fine while card data is leaving, and that gap is the whole problem.

This post explains the mechanics for someone meeting the threat for the first time. It is not a prevention policy and not the formjacking-versus-Magecart taxonomy. It walks the actual sequence: how the code gets in, how it captures the data, and how it leaves. Understand those three moves and you understand why a web application firewall, a SIEM, and a payment processor can all be green while a skimmer runs. cside monitors that browser layer directly, watching every script as it executes and flagging the moment one starts reading fields or calling a domain it never touched before, which is the basis for detecting Magecart in real time rather than after the breach.

The attack in three moves

Every skimming campaign, regardless of which group runs it, comes down to the same lifecycle. Strip away the branding and you get three moves.

MoveWhat happensWhere it lives
InjectAttacker gets their JavaScript to load on your pageA compromised first-party file, third-party tag, or tag manager
CaptureThe script reads card or credential data from the formThe DOM and form event listeners in the browser
ExfiltrateA copy of the data is sent to the attacker's serverAn outbound browser request to an attacker domain

The rest of this post walks each move in order, because the order is what makes the attack invisible.

Move 1: how the code gets onto the page

The attacker needs their JavaScript to execute in the visitor's browser. They have three common routes onto the page, none of which require touching your origin server's logic.

  1. A self-hosted file. They gain write access through a vulnerable plugin, an outdated CMS, or a stolen admin login, then append a few lines to a JavaScript file you already ship. The change is small and often tucked inside legitimate code, so a diff looks unremarkable.
  2. A third-party script. They compromise a vendor whose script you load directly with <script src>, such as an analytics, chat, or A/B-testing widget. Now the skimmer ships from the vendor's domain to every customer who loads your page, and it is never in your repository to find, which is why securing third-party scripts is its own discipline.
  3. A tag manager. They take over a Google Tag Manager container or similar and add one tag containing the skimmer. Every site and page using that container now runs the code, including checkout pages where the tag has no business loading.

The third-party and tag-manager routes scale, which makes them the dangerous ones. One compromised vendor seeds skimmers across every site that trusts it, and a script you approved can pull in another script you never reviewed, the fourth-party problem. This is the supply-chain shape that PCI DSS 4.0.1 requirement 6.4.3 and 11.6.1 target by demanding an inventory and authorization of every script on a payment page. The 2018 Ticketmaster breach took exactly this path: the skimmer reached checkout through a compromised supplier's chatbot script, not Ticketmaster's own code (Wikipedia summary of the 2018 incident).

Move 2: how the skimmer reads your form

Once the script runs, reading the form is ordinary web development turned against you. Reading and modifying the DOM is how every modern framework works, so the skimmer's actions look like normal page behavior. A skimmer typically does one or more of the following:

  • Reads input values directly. It selects the card-number, expiry, CVV, and name fields by their id, name, or autocomplete attributes and reads .value straight from the DOM.
  • Attaches event listeners. It hooks input, keyup, change, or blur on the payment fields, so it captures each keystroke even if the user never submits.
  • Hijacks the submit path. It wraps the form's submit handler or hooks the "pay" button, assembling the full payload at the moment the user commits.
  • Patches network primitives. Advanced skimmers override fetch, XMLHttpRequest.prototype.send, or navigator.sendBeacon to read the real payment request as your own code sends it.
  • Overlays a fake field. Some inject a counterfeit payment iframe on top of the real one, so the shopper types card details straight into the attacker's input. cside's own analysis of a Magecart campaign found a fake payment frame inserted at checkout via a single obfuscated JavaScript line, the kind of swap a server-side scan never sees.

Conditional serving is what keeps it quiet

The skimmer does not fire for everyone. It gates itself so the people most likely to catch it, namely security teams, scanners, and bots, never see the malicious behavior:

  • Path gating. Many skimmers arm only on URLs that match a checkout or login pattern, so the code lies dormant everywhere else.
  • Automation detection. Reading navigator.webdriver returns true in headless and automated browsers, so the skimmer can serve clean code to a scanner and the real payload to a shopper. More advanced variants probe for Selenium globals or Chrome DevTools Protocol (CDP) Runtime leaks to spot instrumented browsers.
  • Once-per-session firing. Exfiltrating a single time avoids duplicate network noise that might stand out in a log.

That arms race is escalating on the attacker side too: cside's Future of Web Security 2026 research report tracked playwright-stealth growing about tenfold across 2025, automation built to defeat navigator.webdriver and similar checks. The same evasion that hides an attacker's tooling from defenders is what hides a skimmer from yours. The code is usually obfuscated on top of all this, which buries intent during a manual review.

Move 3: how the data leaves

Capture is useless to the attacker until the data reaches them. Exfiltration is a single outbound request from the browser, and the attacker has several quiet ways to send it.

MethodHow it looks on the wire
navigator.sendBeacon()A small POST that fires reliably on unload, designed for analytics, so it blends in
fetch() / XMLHttpRequestA standard async request, often to a look-alike domain that mimics a CDN or analytics host
Image requestThe payload is appended to an <img> src as a query string; the browser "loads" an image that is really a data drop
WebSocketA persistent channel for streaming captured keystrokes in near real time

Three properties make this leak nearly impossible to spot from the outside. The request is HTTPS, so it is encrypted like all your other traffic. The destination is usually a typosquatted or freshly-registered look-alike domain that reads like a real vendor. The British Airways skimmer exfiltrated to baways.com, so it does not jump out of a log. And the payload is tiny and often base64-encoded, so it reads like a routine telemetry ping. Critically, this request goes from the browser straight to the attacker; it never passes through your origin, your WAF, or your payment gateway. That is the whole reason the theft is invisible to the server.

Why your server, WAF, and processor never see it

Put the three moves together and the blind spot is obvious. The code loaded in the browser, read the field in the browser, and sent the copy from the browser to a third domain. Your backend only ever saw the legitimate, authorized transaction.

  • A web application firewall inspects requests arriving at your origin. The exfiltration request never arrives there, so the WAF has nothing to inspect.
  • A SIEM aggregates server and infrastructure logs, and the skimmer generates no server event. Fraud monitoring flags purchase anomalies, but the real purchase completed exactly as expected.
  • A payment processor like Stripe or Adyen secures the transaction it receives. If your card fields sit on your own page, a skimmer reads them before the processor is ever involved, and your page still owes its own PCI DSS 4.0.1 6.4.3 and 11.6.1 evidence regardless of the processor.

The attack lives in a runtime your server-side stack cannot reach. A client-side problem needs a client-side defense.

How browser-layer monitoring catches each move

Detection has to sit where the skimmer runs. cside monitors scripts and behavior in the browser, so each move leaves a signal it can act on.

  • Inject shows up as a new or modified script. cside maintains a script inventory and flags additions, changes, and tampered third-party tags when they appear, not weeks later in a fraud report.
  • Capture shows up as behavior. Unexpected listeners on payment fields, code reading inputs it should not, and overrides of fetch or sendBeacon are runtime anomalies against a known-good baseline.
  • Exfiltrate shows up as a destination. cside surfaces outbound requests to domains not on your allowlist, the signature move of a skimmer trying to leave.

Because cside runs in real browsers rather than a clean-room scanner, conditional serving does not hide the skimmer the way it hides from a headless crawler. That same visibility produces the evidence PCI DSS 4.0.1 expects: an authorized inventory of payment-page scripts for 6.4.3, and alerting on unauthorized changes to script content and headers for 11.6.1, both mandatory since 2025-03-31.

Further reading on cside

Simon Wijckmans
Founder & CEO

Founder and CEO of cside. Previously a product manager on Cloudflare Page Shield (now Cloudflare Client-Side Security). Co-chair of the W3C Anti-Fraud Community Group and a Forbes 30 Under 30 honoree. Building accessible security against client-side attacks — web security is not an enterprise-only problem.

FAQ

Frequently Asked Questions

Inside the visitor's browser tab, in the same JavaScript context as your own checkout code. It is not on your server and not in a sandbox. Once a script loads on the page it can read the DOM, attach listeners to form fields, and open network connections to any domain the page's Content Security Policy permits. That shared context is why a single compromised analytics or chat tag can reach the card fields it has no business touching.

It gates itself. Most skimmers check the URL and only arm on a checkout or login path, then inspect the session to avoid sandboxes. A common tell is reading `navigator.webdriver`, which returns `true` in headless and automated browsers; some also probe for Selenium or CDP artifacts so a security scanner sees clean code while a real shopper gets the skimmer. Many fire once per session to avoid duplicate exfiltration. Conditional serving is why a manual review of the page source often turns up nothing.

Often weeks or months, because nothing in the normal monitoring stack changes. The checkout still completes, the payment still authorizes, and orders still fulfill. Skimmers gate their behavior and catch their own errors silently, so casual testing rarely triggers them and a failed exfiltration never breaks the page. Most victims learn of the breach from a card network or a customer report, not from their own systems.

Monitor and Secure Your Third-Party Scripts

Gain full visibility and control over every script delivered to your users to enhance site security and performance.

Start free, or try Business with a 14-day trial.

cside dashboard interface showing script monitoring and security analytics
Related Articles
Book a demo