{"id":49391,"date":"2026-10-20T14:24:12","date_gmt":"2026-10-20T08:54:12","guid":{"rendered":"https:\/\/www.getastra.com\/blog\/?p=49391"},"modified":"2026-10-20T15:18:12","modified_gmt":"2026-10-20T09:48:12","slug":"shopify-supply-chain-attack","status":"publish","type":"post","link":"https:\/\/www.getastra.com\/blog\/vulnerability\/shopify-supply-chain-attack\/","title":{"rendered":"Inside the HulkApps Shopify Checkout Hijack"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Shopify phishing has evolved from the laughable \u201cDear Shopify Merchant\u201d email into one of the most reliable account-takeover vectors in ecommerce. On the same pattern, Shopify shops have recently been hit with a checkout hijack campaign running through HulkApps, Swym, and Selleasy extensions, where shoppers on legitimate stores were redirected to a fake payment page on <code>biliing[.]top<\/code> that captured their card details before forwarding them to the real Shopify checkout.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">German developer Roman Zipp documented the HulkApps path in detail on October 10, 2026, and developer Dan Sutherland surfaced the parallel Swym case on LinkedIn in the same week.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In this blog, we cover how an attack like this works, why it matters more in 2026 than earlier variants, and how to defend against the specific techniques in active rotation right now.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"How_it_Happens\"><\/span>How it Happens<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Storefront supply-chain attacks like the HulkApps hijack follow a common pattern. A legitimate Shopify app ships a storefront script that Shopify reviews, versions, and serves from its CDN, and the merchant installs it and forgets about it.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"866\" height=\"1338\" src=\"\/cdn-cgi\/image\/quality=80,format=auto,onerror=redirect,metadata=none\/https:\/\/cdn-blog.getastra.com\/2026\/10\/dd31074f-image.png\" alt=\"\" class=\"wp-image-49392\" style=\"aspect-ratio:0.6484517304189436\"\/><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\">On every page load, that script calls back to the vendor\u2019s own API for its configuration, and the configuration is treated as trusted input. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If an attacker gets write access to the vendor\u2019s configuration (through a compromised merchant account on the vendor dashboard, a compromised vendor employee, or the vendor\u2019s own infrastructure), they can push code into every store running that app without accessing the merchant\u2019s theme or Shopify\u2019s checkout.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">The HulkApps Case, in detail<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Zipp\u2019s investigation began when his checkout on mechanicalkeyboards.com redirected him to <code>biliing[.]top.<\/code> He checked the URL, confirmed it was not Shopify, and opened Chrome DevTools. The Checkout button had no suspicious listeners attached directly, which told him the hijack was listening higher up in the DOM (document object model, i.e., the browser\u2019s live representation of the page) on window or document. In simpler terms, the malicious script was eavesdropping on the whole page rather than hooking the button alone.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Using Chrome\u2019s event listener breakpoints, he paused on every click listener and found a function literally named hijack, labelled by Chrome as VM142 (its convention for a script injected at runtime). To find the source, he overrode addEventListener with a short shim that paused execution whenever a listener\u2019s code contained the word \u201chijack\u201d. The call stack pointed at hulkcode.js, served from cdn.shopify.com, authored by HulkApps.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Monitoring the extension\u2019s traffic revealed the delivery mechanism. On every page load, hulkcode.js sent one POST to <code>productoption.hulkapps.com\/api\/v2\/store\/get_all_relationships<\/code>, and the response carried an advanced_users.custom_js field holding roughly 22.7 kilobytes of unobfuscated JavaScript.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The storefront script executed that string in the shopper\u2019s browser. A session storage key called <code>__ctf_shim_handoff_done_v1<\/code> ensured each browser was redirected only once per session, which is why merchants testing from their own laptops kept seeing clean checkouts even while the hijack fired for every new visitor.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Dan Sutherland\u2019s Swym Wishlist Plus case followed the same architectural shape through a different field. A configuration value meant to hold the \u201cAdd to Wishlist\u201d button label instead carried HTML with an onerror event handler, which fired at checkout and triggered the same redirect behavior. Swym shipped a fix on October 14 (version 7.0.18) that introduced an escapeHtml() helper across twelve places where configuration had been written straight into the page.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Why_it_Matters\"><\/span>Why it Matters<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The HulkApps hijack is a repeatable attack pattern aimed at a platform that powers roughly 2.83 million live stores worldwide. A single compromised app pushes its payload to every store that has it installed, so attacker effort scales once while damage scales linearly across the install base.&nbsp;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">HulkApps and Swym Wishlist Plus each sit on tens of thousands of stores, which is why serious payment-skimming groups are now moving upstream to the app layer. Shoppers pay the downstream cost, often without noticing, because the attack forwards them to the real Shopify checkout afterward and the order completes normally.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The compliance exposure is very costly for Shopify merchants. All 50 US states plus Canada\u2019s <strong>PIPEDA<\/strong> impose breach notification obligations once personal information is exposed, with state-level timelines ranging from 30 to 90 days and California\u2019s <strong>CCPA\/CPRA<\/strong> adding a private right of action worth $100 to $750 per affected consumer in statutory damages.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">On top of this, Visa and Mastercard treat a confirmed account data compromise as a trigger for mandatory PCI Forensic Investigator (PFI) engagement at the merchant\u2019s cost, which routinely runs $50,000 to $200,000 before any card brand fines (typically $5,000 to $100,000 per month until remediation) or chargebacks are counted. For mid-size SMBs, the compliance tail on a confirmed HulkApps-class incident can comfortably exceed the direct fraud losses by an order of magnitude.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"What_Merchants_Should_Do_Right_Now\"><\/span>What Merchants Should Do Right Now?<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The defenses fall into two buckets: things a merchant can act on in Shopify Admin this week, and a standing cadence that catches the next variant.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1. Audit installed apps today<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Open Settings \u2192 Apps and sales channels, remove anything unused, and for apps that remain, note whether they inject a storefront script, what scopes they hold, and whether their vendor dashboard has a \u201cCustom JavaScript\u201d or \u201cCustom HTML\u201d field. Those fields are the specific attack surface the HulkApps case exploited.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Rotate credentials and enable phishing-resistant authentication<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Rotate your Shopify admin password and enable passkeys or an authenticator app on every account with admin access. Do the same on every connected app vendor dashboard (HulkApps, Swym, Selleasy, Privy, Hextom, Qikify, and any other third-party vendor you have an account with), because a compromised merchant account on the vendor side is one of the possible entry points for this attack class.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. Run the incognito checkout test weekly<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Open a fresh private browsing window, add any item to the cart, press Checkout, and verify the destination is your custom domain or checkout.shopify.com. Because the HulkApps payload fired only once per session per browser, test from multiple devices and clear browser storage between runs.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Monitor outbound network traffic monthly<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Record a full checkout in Chrome DevTools Network tab and diff the hostnames against last month\u2019s list. Any new domain, especially lookalikes of Shopify, checkout, billing, or account, or sketchy TLDs like .top, .xyz, or .icu, needs investigation the same day.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Audit staff and collaborator permissions quarterly<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Shopify\u2019s staff permissions are granular. Remove ex-employees, ex-contractors, and anyone whose role no longer needs admin access, and scope what remains to the minimum the role actually requires. Over-permissioned accounts increase the blast radius, i.e., how far a single compromised login can reach.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">6. Enforce a Content Security Policy on the storefront<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A Content Security Policy (CSP) is a browser-enforced allowlist of script sources, i.e., the browser refuses to load scripts from any domain not on your pre-approved list.&nbsp;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For higher-volume stores and Shopify Plus merchants, a tight CSP would have blocked the fake checkout redirect at the browser level even if the compromised app continued to execute. Document your allowlist and review it every time you install or update an app.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">7. Document a kill switch and an incident playbook<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Decide now, in writing, who has authority to turn off apps, pull the storefront offline, and rotate credentials, and make sure that person has standing access without needing to escalate.&nbsp;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Your playbook should include turning off the suspected app, clearing browser storage during testing (the Swym case showed that disabling the app did not immediately stop the behavior because the config was cached in localStorage), notifying your payment processor, and preparing customer communications.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Where_Astras_Autonomous_Penetration_Testing_Fits_in\"><\/span>Where Astra\u2019s Autonomous Penetration Testing Fits in<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1920\" height=\"933\" src=\"\/cdn-cgi\/image\/quality=80,format=auto,onerror=redirect,metadata=none\/https:\/\/cdn-blog.getastra.com\/2026\/09\/ff3fbe05-image.png\" alt=\"\" class=\"wp-image-48990\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Shopify\u2019s shared responsibility model leaves the storefront, custom apps, Admin API integrations, and any custom backend in your lap. Those are the layers Astra\u2019s autonomous pentest helps you harden against cyberattacks.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For a Shopify store, that means Astra\u2019s autonomous pentest attempts to exploit every finding it surfaces against the internet-exposed storefront and custom-built code, reporting back only what is reachable and exploitable, with full PoC and remediation path.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Moreover, our autonomous pentest agents can also surface the storefront\u2019s third-party script inventory, flag newly appearing scripts against the known baseline, test the Admin API surface for authentication and authorisation flaws, and continuously validate the controls that PCI DSS 4.0.1 requirements 6.4.3 and 11.6.1 are written to enforce.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Not sure whether you need a Shopify penetration test? Take this questionnaire to find out.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Has your storefront been pentested in the last twelve months?<\/li>\n\n\n\n<li>Do you have a current inventory of every third-party script running on your checkout page?<\/li>\n\n\n\n<li>Are your Admin API tokens stored in a secrets manager, scoped, and rotated?<\/li>\n\n\n\n<li>Do you have Content Security Policy headers configured on your storefront?<\/li>\n\n\n\n<li>Would you detect a new script appearing on your checkout within 24 hours?<\/li>\n\n\n\n<li>Do you have a tested incident playbook for a checkout-hijack scenario?<\/li>\n\n\n\n<li>For Plus merchants: have you mapped every script on the payment page for PCI DSS 4.0.1 compliance?<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">If three or more of those are a \u201cno\u201d or a \u201cnot sure,\u201d a Shopify security assessment with Astra is worth a conversation.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Book a demo today <a href=\"https:\/\/www.getastra.com\/contact-us?tab=pentest_sales\">here.<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Final_Thoughts\"><\/span>Final Thoughts<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The HulkApps hijack is the kind of incident that becomes a reference point, because it demonstrated that the economic structure of the Shopify app ecosystem creates a reliable supply-chain attack path. Any app that fetches runtime configuration from the vendor\u2019s own servers and treats fields in that response as code or as HTML inserted into the DOM carries the same risk profile, whether the attacker has noticed yet or not.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The practical lesson for merchants is that app review at install time is only the first checkpoint. The app\u2019s behavior at runtime, every day it stays installed, is the surface that actually matters. Zipp\u2019s investigation is the model for how to watch that surface, and the discipline of running those checks weekly, paired with periodic third-party testing of the stack as a whole, is what will keep your Shopify store safe.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\u200b<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Shopify phishing has evolved from the laughable \u201cDear Shopify Merchant\u201d email into one of the most reliable account-takeover vectors in ecommerce. On the same pattern, Shopify shops have recently been hit with a checkout hijack campaign running through HulkApps, Swym, and Selleasy extensions, where shoppers on legitimate stores were redirected to a fake payment page &#8230; <a title=\"Inside the HulkApps Shopify Checkout Hijack\" class=\"read-more\" href=\"https:\/\/www.getastra.com\/blog\/vulnerability\/shopify-supply-chain-attack\/\" aria-label=\"Read more about Inside the HulkApps Shopify Checkout Hijack\">Read more<\/a><\/p>\n","protected":false},"author":138,"featured_media":49393,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[723],"tags":[],"class_list":["post-49391","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-vulnerability"],"_links":{"self":[{"href":"https:\/\/www.getastra.com\/blog\/wp-json\/wp\/v2\/posts\/49391","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.getastra.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.getastra.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.getastra.com\/blog\/wp-json\/wp\/v2\/users\/138"}],"replies":[{"embeddable":true,"href":"https:\/\/www.getastra.com\/blog\/wp-json\/wp\/v2\/comments?post=49391"}],"version-history":[{"count":3,"href":"https:\/\/www.getastra.com\/blog\/wp-json\/wp\/v2\/posts\/49391\/revisions"}],"predecessor-version":[{"id":49397,"href":"https:\/\/www.getastra.com\/blog\/wp-json\/wp\/v2\/posts\/49391\/revisions\/49397"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.getastra.com\/blog\/wp-json\/wp\/v2\/media\/49393"}],"wp:attachment":[{"href":"https:\/\/www.getastra.com\/blog\/wp-json\/wp\/v2\/media?parent=49391"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.getastra.com\/blog\/wp-json\/wp\/v2\/categories?post=49391"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.getastra.com\/blog\/wp-json\/wp\/v2\/tags?post=49391"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}