Hijacked Shopify Apps Sent Shoppers to Fake Checkouts. Here's What to Check.

In October 2026, three Shopify apps were hijacked to send shoppers to fake checkout pages. What happened, what's unknown, and a read-only store check.

A checkout button whose path splits: one line leads to a real checkout, a red line leads to a look-alike page that takes the shopper's card

Over eight days in October, someone used at least three Shopify apps to send shoppers to fake checkout pages. The shopper clicked Checkout, landed on a convincing copy of a checkout on a .top domain, typed in a card, and was then passed along to the store's real checkout. The order went through. The card number went somewhere else.

Here's what's confirmed, what isn't, and what you can check on your own store this afternoon without touching anything.

What happened, in order

October 10: Hulk Product Options. Developer Roman Zipp found it while shopping. He clicked Checkout on a Shopify store and landed on a lookalike page. His password manager offered his card's first name for the "First name" field, which is what made him look at the URL. He traced it to the Hulk Product Options app, reported it to the developer, to Shopify, and to abuse lists, and Shopify removed the hijack from that store 16 minutes after escalating it internally. HulkApps later confirmed that "an exploit introduced unauthorized configurations into the Hulk Product Options app," which "redirected some checkouts to a fake external checkout page." HulkApps says Shopify temporarily disabled the app's theme extension, then restored it after the code was removed. HulkApps has not published a time window.

October 13: Selleasy. Logbase, the developer, says "an unauthorized party gained access to an internal Selleasy tool" and used it to add a malicious script to the Selleasy settings of a number of stores. The stated window is 07:47 to 15:00 UTC. iTnews reports that Shopify confirmed removal at 15:40 UTC. Logbase's incident page says it found no evidence of a breach of its backend or database. Per iTnews, Logbase "could not rule out shoppers handing over their details."

October 14: Swym Wishlist Plus. Swym says that "between approximately 10:06 UTC and 11:56 UTC, an unauthorized party made a change to our Swym Wishlist Plus app configuration" that loaded a script on "a limited subset of storefronts." Mitigations started at 15:02 UTC and were fully deployed at 16:32 UTC.

October 18 onward: Swym, second wave. Swym's incident FAQ says new attempts were made to add malicious code to storefronts through the app. This time, Swym says, "the activity used the app's access, not your staff accounts." Swym paused the app for all merchants at once, revoked Shopify access for all of its apps, and rotated credentials. Fudge reported that an earlier version of that FAQ dated the start to 21:17 UTC on October 18. The current version doesn't give a start time.

Shopify's checkout was not the thing that broke

No source in this whole mess says Shopify's checkout itself was breached. The fake pages lived on outside domains. After capturing the card, the fake page sent the shopper on to the real checkout.

That's the nasty part. Your orders may not have dropped. The shopper still bought the thing. A flat conversion rate tells you nothing here.

How it worked

The clever bit is where the code lived. It wasn't in your theme.

In the Hulk case, the app's loader file was legitimate and served from Shopify's own CDN. On page load it asked HulkApps' servers for the store's settings. The response included a field for merchant "custom JavaScript" (advanced_users.custom_js), and that field held about 22.7 KB of attacker code that the app then ran on the page. Selleasy's version used its "Custom JS" setting. In Swym's first wave, developer Dan Sutherland found the payload stuffed into the "Add to Wishlist" button label, as HTML that ran when the app wrote that label onto the page.

So in those three cases, the theme files stayed clean. Nothing showed up in a theme diff. As c/side points out, the app file on Shopify's CDN never changed, so integrity checks on that file passed too. The bad code arrived as data from the vendor's server.

(Swym's second wave is the exception. Swym says that one used the app's own Shopify access, and it tells merchants to look for theme file edits made by the Swym app.)

The script was also built to be hard to reproduce. It fired once per session and marked itself in the browser's sessionStorage with keys starting __ctf_ (__ctf_shim_handoff_done_v1 and __ctf_checkout_txn_v1). Test checkout twice in the same browser session and the second try looks perfectly normal. That's how you end up with a merchant saying "I tested it, it's fine."

The fake pages were good. The Swym payload copied the shopper's real cart: products, variants, quantities, totals, currency.

Confirmed incidents vs. delisted apps

This is where most of the chatter online goes wrong, so I'm going to be strict about it.

Confirmed by the developer, October: Hulk Product Options, Selleasy, Swym Wishlist Plus. That's the list. Three apps.

Switched off and delisted, but not linked to the campaign by the developer: Boost AI Search & Filter and Privy. Boost's status page says it switched off its theme app extension for all stores on October 17 while it fixed "the underlying cause," and Shopify re-enabled it on October 18. It doesn't mention phishing. An archived copy of Privy's status page from October 17 read "We are investigating a security issue affecting Privy displays," and Privy turned off displays on all stores. Privy's current status page describes it as an outage. Merchant comments on Zipp's post claim redirects through both apps. Zipp himself labels them "unconfirmed but de-listed."

Delisted, with no reported incident at all: As of October 20, the App Store listings for Rebuy, Upcart, AfterSell, and Hextom: Free Shipping Bar read "not currently available." Zipp also lists Consentmo GDPR Compliance as delisted, citing a "confidential source." None of these developers has reported a security incident, and none has said why the listing is down. Rebuy's listing also went down in mid-September and was back by September 19.

A delisting is not evidence of compromise. The "not currently available" banner looks the same whether Shopify pulled the app or the developer pulled it. Apps get delisted for plenty of reasons. Setka counted 126 delisted apps, 89 of them dated October 15, and says plainly that the count "does not establish" they were compromised. It floats Shopify's API version cutoff on October 16 as a possible non-security explanation, and also says it has no evidence for that. Don't rip out an app because it showed up on a list.

What Shopify has said

Two things, on the record. A Shopify spokesperson told iTnews on October 17: "When an app falls short, we act." The spokesperson said that can "include delisting an app to protect merchant security," and that merchants "stay in control of the apps on their store."

Then on October 20, Shopify staff posted "Securing your app, together" to the developer forum and pinned it site-wide. It opens: "Security is the most important thing you can work on right now." It asks every app developer to act "this week": run the AI Toolkit security check, move to expiring access tokens ("This will soon be required for all public apps"), turn on two-step authentication for Partner, hosting, CDN, repo, and email accounts, and "treat rendered data as untrusted," including data from the developer's own servers. That last one is this attack in a sentence. Shopify also says it plans tighter boundaries for storefront app code, IP restrictions so API keys only work from the developer's servers, and higher App Store security requirements, with details and timelines to come.

Neither statement names the campaign, an app, a domain, or a count. As of October 20, I can't find a merchant-facing Shopify blog post, help article, or status page incident about it.

This has happened before

Two earlier cases get lumped in with this one. Both are separate.

  • Qikify, July 22. Qikify confirmed that two of its apps, Sticky Add to Cart and Mega Menu, sent some shoppers to a fraudulent page through two customizable HTML fields in app settings. Nothing was written to themes. Same shape: fake card form, then the real checkout. Qikify blames a compromised credential and says its case is "NOT PART OF THIS WEEK'S WAVE."
  • Hextom, August. There's no Hextom statement. The evidence is a merchant's App Store review from August 30 describing a checkout redirect that stopped once the Free Shipping Bar app was removed, and a LinkedIn post the next day. Sources disagree on which Hextom app was involved. Zipp lists it as resolved.

Indicators

These are the phishing domains named by Zipp, Dan Sutherland, Swym, and merchants (Zipp, Swym FAQ, Shopify Community). They're defanged on purpose. Don't visit them.

  • biliing[.]top (note the misspelling)
  • checkout-confirm[.]top
  • order-confirm[.]top
  • account-confirm[.]top
  • billing-confirm[.]top
  • checkout-guard[.]top
  • checkout-secure[.]top

Browser-side markers: sessionStorage keys starting with __ctf_ (Zipp), and for Swym's first wave, a localStorage entry named swym-rconfig_cache that kept the payload cached even after the app was disabled.

A read-only check for your store

None of this changes anything on your store. Don't submit forms, don't go to checkout, and don't save anything in an app's settings while you look.

  1. Check your app list. Settings > Apps. Look for Hulk Product Options, Selleasy, or Swym Wishlist Plus. Then open each storefront app's own settings and note any field for custom JavaScript, custom code, or custom HTML. Zipp recommends exactly this. Screenshot it. Don't edit it.
  2. Check your app embeds. Online Store > Themes > Customize, then the App embeds icon in the sidebar (Shopify's help doc). Any embed that's switched on is loading on every page. You should recognize every one of them.
  3. Open a fresh private window. No extensions, a new session. That matters, because the script fired once per session.
  4. Open DevTools before you load the page. Network tab, "Preserve log" on. Load a product page, then your /cart page. Stop there.
  5. Read the Network tab. Filter for .top (WitsCode's suggestion). Then scan the list of domains loading scripts. Expect your own domain, Shopify's CDN, and the vendors of apps you actually run. Anything you can't match to an app is worth a question.
  6. Check where the Checkout button goes. Inspect the checkout button or cart form on /cart. Its target should be /cart or /checkout on your own domain. An outside domain is a red flag. Look, don't click.
  7. Check storage. DevTools > Application > Session storage, and Local storage. Any key starting with __ctf_ matches this campaign.
  8. If you ran Swym Wishlist Plus, follow Swym's FAQ: look for theme file edits made by the Swym app, and search your theme files for checkout-guard.

A clean result today doesn't tell you about October 13. The confirmed windows lasted hours, and the developers say the code is gone. The better signal is your inbox: customers mentioning a weird extra payment page, a payment error before checkout, or card fraud after buying from you (WitsCode). If you find something, screenshot it with the address bar visible, save the URL, and contact Shopify Support and the app developer. Swym also reminds merchants to check their own notification duties under breach laws and GDPR.

For app developers

Shopify CLI 4.9.0, released October 8, added shopify app security check. Shopify announced it on October 15. It scans your app's codebase, its configuration across extension points, and its dependencies. Among roughly 36 rules, the docs list several that cover this class of bug:

  • UNSAFE_INNERHTML: unsafe HTML assignment
  • TEXT_SETTING_HTML_SMUGGLING: a text setting rendered as unsafe HTML
  • THEME_EXTENSION_XSS: cross-site scripting in a theme extension
  • LIQUID_UNSAFE_RENDER: unsafe output of a metafield or setting

Its OPEN_REDIRECT rule covers auth callbacks, not storefront checkout redirects. As of CLI 4.9.4, it needs Git 2.38 or later, and it reports finding counts to Shopify as telemetry.

If you use Shopify's AI Toolkit, the same check runs from your coding agent with the prompt /shopify Check my app for security vulnerabilities. The agent runs the deterministic scan, investigates the flagged items, and summarizes (docs).

Two caveats. First, this shipped before the campaign was discovered, and Shopify's announcement doesn't mention it. Second, Shopify's own post says "a clean report isn't a guarantee of security." My read: a source-code scanner checks how your code renders settings. It can't tell you whether someone has access to your internal admin tool. If your app lets merchants paste JavaScript or HTML into a setting, look at what the affected vendors did after the fact. Logbase locked its Custom JS setting so no tool or API could change it. Swym added sanitization, rotated secrets and internal credentials, and added another layer of authentication.

What we don't know

  • How many stores or shoppers were affected. No developer and no Shopify statement gives a number. Zipp knew of two stores on October 10 and heard from five to seven merchants by October 15. Selleasy has 49,000+ active stores, but that's its install base, not a victim count.
  • The root cause. HulkApps says "an exploit." Logbase says access to an internal tool. Swym says an "access channel," then the app's own access. None has published how the attacker got in.
  • Whether it's one actor. The same biliing[.]top domain showed up through both Hulk and Selleasy, and HulkApps calls it "a wide attack that also impacted multiple Shopify apps." Nobody has published attribution. Zipp says the frequency is "very very suspicious" but that he "can't conclude anything yet."
  • Which apps, per Shopify. Shopify hasn't named any, including in its October 20 developer post.
  • Whether the list is complete. On October 19, a merchant with three affected stores reported redirects to checkout-guard[.]top and hadn't found the source.

I'll update this post as developers publish root causes.

The bigger lesson

Every app you install gets to run code in front of your customers, and for a lot of apps, that code is partly decided on the vendor's server, not in your theme. That's not a reason to panic-uninstall. It is a reason to know exactly what's running on your storefront and why, and to trim what you don't need.

If you want a second set of eyes on your app stack, that's what we do. Reserve Your Consultation.

Thanks to Roman Zipp for finding this, documenting it in public, and keeping his post updated. If you read one source on this, read his.

-- Kurt Elster

Let's start something new