Been reading up on the checkout-hijacking wave from the last couple of weeks, and the scary part is how invisible it was. Between about Oct 10 and 20, at least three App Store apps were used to send shoppers to fake checkout pages on look-alike .top domains, capture their card details, then forward them to the real Shopify checkout so the order completed as normal. The merchant just saw an ordinary order - the researcher who first flagged it had seven different merchants independently report the exact same thing.
Shopify’s own checkout wasn’t breached - the malicious code came in through the app developers’ own systems, and the affected apps have since been fixed or de-listed. For context, Letsmetrix reported 512 apps were unlisted from the store in the surrounding month (169 of them during the Oct 10–20 window), though an unlisting on its own isn’t proof of compromise.
What made it so hard to catch: the payload arrived as app data, not theme code (one case was ~22 KB of JS served back by the app’s own API under a custom-JS setting), so a theme diff showed nothing. It also fired only once per browser session, so re-testing checkout in the same tab looked completely normal.
Quick way to check a store:
Test checkout in a fresh private window (DevTools open, “Preserve log” on), new window each time.
Watch for any script or request to a .top domain, and confirm checkout stays on your own domain or Shopify.
In DevTools > Application, look for session/local storage keys starting with _ctf.
Audit any app field that accepts custom JS or HTML - every confirmed case abused one.
Anyone here actually run into this on a store you manage?
We have brought malicious stores to Shopify’s attention before. They did not care. Here a a snippet from an old support email:
… you have a Shopify Partner that has created 10 or so shops to get around our blocking, they change their IP address, they change their email. Month after month for 4 months
Shopify:
… We cannot share or discuss the outcome of these investigations for privacy reasons.
Blocking the merchant in this case is the best course of action to prevent them from installing the app, and to communicate with them directly. We cannot action anything further on our end.
As a business they want to make it as easy as possible to create shops. This where they make their money. Any friction can hinder onboarding so if there are some “small” security issues here and there no biggie! Meanwhile I need to upload my ID
That sounds really frustrating, especially four months of the same partner coming back under new shops. The asymmetry you point out is real too: partners go through ID checks, while abuse on the store side can keep resetting itself.
Out of curiosity, how did you end up mitigating it? Fingerprinting the shops, or something on the app side? That could be useful for others here dealing with the same thing.
I do not want to say because this is becoming a more serious problem but it involves a checking a variety of criteria and a blacklist. It works but it’s not perfect. We monitor it closely. User messaging is important because they very well may be legit and need a way to proclaim their innocence, heh.
Hi @Kate_Ju. Since the payload came back as app data, a theme diff won’t show it, so audit the other injection points. Check Settings > Customer events for web pixels you don’t recognise, and query the Admin GraphQL `webPixels` field to see what’s actually registered at checkout. For older installs, list legacy tags with `GET /admin/api/2024-10/script_tags.json`. Any app field returning custom JS from its own API needs reviewing directly, not through the theme. Keep testing in a new private window each time, since it fires once per session.
Mark this as the solution if it pointed you somewhere useful.