Stolen Card Data Was Moving Through Stripe the Whole Time

When a checkout page loads on a compromised Magento store, nothing looks wrong. The Stripe payment widget is there. Google Tag Manager is doing what Google Tag Manager does. Traffic flows to domains the store already whitelists. That’s exactly the problem — and the point.

Ecommerce security firm Sansec identified a Magecart campaign that routes both its malicious payload and the stolen card data through api.stripe.com. The operation uses Google Tag Manager containers as the delivery vehicle and Stripe’s customer records API as an impromptu data warehouse. Because stores grant implicit trust to both googletagmanager.com and api.stripe.com, the skimmer sidesteps Content Security Policy rules and network filters that would otherwise flag outbound traffic to an unfamiliar domain.

How the Infection Chain Works

The attack begins with malicious code embedded inside what appear to be legitimate GTM containers. Google Tag Manager is a standard tool that lets site operators inject analytics scripts, ad tags, and tracking pixels without editing source code directly — which is partly why it’s so useful as cover. When a shopper navigates to a checkout page, the GTM container activates and queries Stripe’s API for a specific customer record: cus_TfFjAAZQNOYENR.

That customer record isn’t a real buyer. It’s a storage object. The attacker has placed JavaScript inside the metadata fields of that record, and the skimmer reads it back out, reassembles it, and executes it using new Function() — a classic technique for running reconstructed code that would look suspicious if written out in full. The resulting script targets Magento and Adobe Commerce checkout pages, harvesting credit card numbers, expiration dates, CVV codes, customer names, billing addresses, email addresses, and phone numbers.

What gets captured doesn’t leave the browser immediately. The stolen data is concatenated into a single string, obfuscated using an XOR operation, and written to local storage rather than transmitted at the moment of theft. A separate retrieval routine runs right after page load and then every 60 seconds. It splits the stored data blob in half, creates a new Stripe customer object in the attacker’s account, and writes the payment data into that object’s metadata fields. Every compromised card becomes a fake customer record. Every fake customer record sits inside Stripe’s own infrastructure. Once the data is copied to Stripe, the local storage entry is wiped to remove traces and prevent the same card from being uploaded twice.

Why api.stripe.com Is So Effective as an Exfiltration Channel

Most merchant websites that use Stripe have already told their security stack to trust api.stripe.com. It’s on the allowlist. Traffic to it doesn’t trigger alerts.

That’s the structural vulnerability this campaign exploits. CSP headers exist to prevent unauthorized scripts from sending data to attacker-controlled servers — but when the attacker uses a server the store already trusts, the policy fails at its core purpose. The attackers didn’t break through a filter. They walked through a door the store left open on purpose.

A Second Variant Uses Google Firestore Instead

Sansec also identified a variant that swaps Stripe for Google Firestore — Google’s cloud database service — as the exfiltration backend. In this version, the payload is retrieved from a Firestore document named tracking/captcha inside a project called braintree-payment-app. The stolen data is stored under a different localStorage key: _d_data_customer_.

The naming is deliberate. “Braintree” is a well-known payment processor owned by PayPal. “Captcha” is a routine component of bot-protection flows. Any analyst skimming through traffic logs would likely read both as background noise rather than indicators of compromise. The Firestore variant follows the same structural logic as the Stripe version — trusted infrastructure, camouflaged naming, local staging before exfiltration — just with a different cloud service absorbing the stolen data.

Timeline and Scope

The Stripe customer record used to deliver the skimmer payload was created on December 24, 2025. That date sets the earliest plausible start of the operation, though infections could have occurred on any store that loaded the compromised GTM container from that point forward.

Magento and Adobe Commerce are the confirmed targets. Both platforms are historically popular with Magecart operators because they power a substantial share of independent online retail and frequently run older plugin versions that introduce script injection opportunities. GTM is used by a wide range of Magento merchants, making it a natural infection vector — once an attacker gains write access to a GTM account or hijacks an existing container, they can deploy the skimmer without touching the store’s underlying codebase at all.

The use of new Function() to execute reassembled JavaScript is also worth noting. It’s a technique that can evade static analysis tools that scan for known malicious function signatures, since the malicious code doesn’t exist as a complete string anywhere in the payload delivery chain until it’s reconstructed inside the browser.

What Stores and Shoppers Are Looking At

For merchants, the attack is difficult to catch through conventional monitoring. If your security controls trust Stripe and GTM by default, and your logs show traffic flowing to api.stripe.com, nothing looks anomalous. Detection requires either integrity monitoring on GTM containers — checking that the scripts loaded match what was intentionally deployed — or behavioral analysis that flags unusual Stripe API call patterns, such as calls that create customer records without any corresponding purchase flow.

Tightening CSP rules to distinguish between expected Stripe API usage (payment processing) and unexpected usage patterns (customer record creation at checkout without an actual transaction) would add friction for this type of attack, though it requires careful implementation to avoid breaking legitimate payment flows.

For shoppers, the most direct mitigation is using single-use virtual card numbers for online purchases. Several major card issuers and fintech services offer virtual cards with per-transaction or per-merchant spending limits. If the card number captured by a skimmer is already expired or capped at the exact amount of the original transaction, it can’t be used again. The stolen credential still enters the attacker’s Stripe account as a fake customer record — but it has nowhere useful to go.

The Broader Pattern This Campaign Reflects

Magecart operations have evolved well past the early days of crude JavaScript injected directly into payment form fields. This campaign illustrates where the technique now sits: cloud-native exfiltration over trusted channels, metadata fields used as covert data storage, and infrastructure that blends into normal merchant operations well enough to stay resident for weeks or months.

Using a legitimate service as both a payload host and a data sink isn’t new in concept, but executing it against Stripe — a platform that merchants are specifically configured to trust with financial data — is a notable refinement. The Firestore variant suggests the attackers are already building flexibility into the approach, with at least two functional backends available depending on what the target environment allows.

The Stripe customer record cus_TfFjAAZQNOYENR was created December 24, 2025. Whether it’s still active — and how many card records now live alongside it in that account — is a question Stripe would need to answer.