When scanners miss the attack: how Cloudflare Client-Side Security protects storefronts Cloudflare's Page Shield machine learning model detected all eight malicious JavaScript payloads across four client-side attacks on storefronts, while seven of the eight were entirely absent from VirusTotal and URLScan returned no malicious verdict for any of them. The GNN-based system, which flags under 0.3% of all analyzed traffic as malicious, reasons through JavaScript as a syntax tree graph rather than relying on known URL or byte signatures, and had previously caught malicious npm packages and an in-the-wild Magecart payment skimmer. One Lnkr-family payload sat indexed by URLScan for nearly two and a half years with "No classification," including during a direct scan in January 2024, before Page Shield ML surfaced those exact bytes live on an online retailer's storefront. When scanners miss the attack: how Cloudflare Client-Side Security protects storefronts A modern storefront can look perfectly healthy while malicious JavaScript works underneath: siphoning affiliate revenue, hijacking searches and clicks, tampering with analytics, or asking a remote server what to execute next. Pages load, products appear, and checkout works — yet the browser may be quietly doing something the site owner never authorized. That is the blind spot our Client-Side Security machine learning ML model https://blog.cloudflare.com/client-side-security-open-to-everyone/ is built to expose. This post follows four operations, spanning eight payloads, that our Page Shield ML uncovered in the wild. The detection of these malicious payloads was automated; humans verified each finding only after the system had flagged it. When we afterward reviewed the campaigns using security scanning tools, seven of the eight payloads were entirely absent from VirusTotal, and URLScan returned no malicious verdict for any of them. Page Shield ML https://www.cloudflare.com/products/client-side-security/ , meanwhile, caught all eight in live traffic. For instance, while security research documented the broader Lnkr https://www.netskope.com/blog/ad-injector-dulls-chromes-luster family years earlier, one specific payload version sat indexed by URLScan for nearly two and a half years with “No classification,” including during a direct scan in January 2024. Only in this case had VirusTotal ingested the payload earlier: while it currently flags the script as malicious, public history does not reveal when that verdict was first assigned. Meanwhile, Page Shield ML independently surfaced those exact bytes live on an online retailer's storefront. More broadly, a hash can be known long before the code behind it is classified as malicious. If your defense waits for that label, you are already late. You need ML that can unravel the JavaScript itself and judge it at scale. Indeed, seeing a file is not the same as understanding it. The tricky part was that the four operations shared no universal signature or common concealment technique. One remained dormant unless the device, country, time, referrer, or browser state matched what it was waiting for. Another concealed a clickless affiliate request within an invisible iframe. Others intercepted clicks, suppressed monitoring, or conditionally loaded additional code from remote servers. To catch them, you have to watch how those pieces work together: when the script wakes up, what it hides, what it intercepts, and what it fetches next. Checking the page once is not enough; as these cases show, such scripts are built to stay quiet until the right victim shows up. That is why ongoing browser visibility makes the difference between catching an attack and missing it entirely. How we detect and label JavaScript at scale The same GNN graph neural network that flagged the four operations in this post had already caught malicious npm packages https://blog.cloudflare.com/how-cloudflares-client-side-security-made-the-npm-supply-chain-attack-a-non/ finding-needles-in-a-3-5-billion-script-haystack and an in-the-wild Magecart payment skimmer https://blog.cloudflare.com/navigating-the-maze-of-magecart/ proactive-detection . The GNN does not treat JavaScript as a flat chunk of text; it reasons through the code as a graph: a syntax tree https://blog.cloudflare.com/how-we-train-ai-to-uncover-malicious-javascript-intent-and-make-web-surfing-safer/ using-syntax-trees-to-classify-malicious-code connecting code symbols and exposing what calls what, what the attacker tried to bury, and what still phones home. That structure helps it recognize suspicious patterns across minification, renaming, and some obfuscation without relying on a known URL or byte signature. The few scripts that the GNN flags as malicious under 0.3% of all analyzed traffic go to a lightweight large language model LLM https://www.cloudflare.com/learning/ai/what-is-large-language-model/ on Workers AI for a live second opinion https://blog.cloudflare.com/client-side-security-open-to-everyone/ adding-an-llm-based-second-opinion-for-triage . This further reduces false positives while keeping recall high. When the LLM corroborates the GNN, customers are alerted. To investigate the most complex scripts at scale, we use a cohort of frontier models, which we call teachers an ensemble of automated judges . The cohort draws leading models from around six different families, including open-weight models running on Workers AI. We spin up each as an agent to analyze the same suspicious script in its own fresh, independent session. When useful, their agentic tool access lets them use a restricted JavaScript evaluator to unpack small snippets and reveal concealed behavior. We will soon extend this workflow with Cloudflare Sandbox https://developers.cloudflare.com/sandbox/ for deeper analysis in isolated environments. The frontier models sometimes disagree, especially on the most intricate scripts. We treat that disagreement as signal, not noise. Each label becomes a vote, weighted by the model's score in the Artificial Analysis Intelligence Index https://artificialanalysis.ai/leaderboards/models , producing a probability distribution over four labels: benign, payment skimming magecart https://blog.cloudflare.com/navigating-the-maze-of-magecart/ , other malware, and cryptomining. Human reviewers therefore need only examine scripts flagged as malicious or lacking a clear two-thirds majority. We then feed those label distributions back into GNN training, helping it distinguish ever more nuanced cases. This feedback loop is still partly manual, though we are starting to automate it. Four malicious JavaScript operations we caught These four operations do very different things, from commission theft to stolen analytics on shoppers the store already paid to acquire. Stealing a commission is not like skimming a credit card; likewise, hijacking search is not like stealing a password. If an ML model only knows one of those tricks, it will sleep through the others. Instead, our Page Shield ML has to stay attuned to every kind of hostile behavior. Now, let’s dig deeper into each operation and how it worked. | Operation | Customer impact | What the script does | |---|---|---| | 1 After-hours affiliate-commission hijacker | Hijacks affiliate commissions | Mobile device & time gates; dynamic page monitoring; click interception; multi-day cooldown | | 2 Clickless affiliate theft | Steals affiliate commissions without user clicks | Off-screen iframe; auto-clicking hidden link fallback; spurious IP-lookup fetch & time gates; hourly affiliate rotation | | 3 Old search saboteur, now storefront backdoor | Tracks users and opens a backdoor for arbitrary remote JavaScript execution | Legacy keyword silencing; localStorage opt-out; telemetry; remote code loading | | 4 Paid-mobile cloaker | Blinds the store on campaign-tagged mobile visitors, attempts to replace ads and analytics, and hides support | Host, viewport & UTM tag gates; 325-entry IP substring list; disables 9 monitoring/analytics tools; zero-pixel tracking beacons | Operation 1: The after-hours affiliate-commission hijacker Picture a quiet Sunday afternoon: a shopper on a phone taps a product. Instead of following the tap normally, the script opens a product or campaign landing page from an attacker-preselected list in a new tab and sends the original tab through an affiliate route. The storefront still appears to work. If the shopper completes a purchase either then or later , the detour hijacks the attribution, crediting the sale and any resulting commission to an account that did not earn the referral. What the shop lost The shop could pay an unearned commission to an account that did not bring the shopper. Worse, if a legitimate partner had made the referral, the forced request could misattribute it, diverting credit and a potential payout from the partner who did the work. The damage could outlast one commission: partners who stop trusting the attribution system may also stop trusting the retailer behind it. Attack chain Qualified mobile visitor → intercepted product tap → script-selected page opens in new tab + original tab follows attacker’s affiliate route How it stayed hidden We found five related script builds: two active and three paused when captured. Each active variant uses a different set of gates before it acts, checking things like the visitor’s device and local time, whether the trick has run recently, whether a product button has appeared, and whether someone actually clicks it. That maze of rules keeps the malicious behavior out of sight during a brief automated visit unless the variant’s specific conditions are met. The active scripts use a MutationObserver a JavaScript API to watch for product tiles and buttons that dynamically appear after the page is first loaded. This lets them intercept clicks on those late-arriving elements, while a crawler that loaded the HTML once and stopped there could miss the redirect path entirely. In the active later variants, the script intercepts a qualifying click and writes a three-day cooldown to localStorage staying dormant on that device for days . It then executes a dual-tab maneuver: popping an attacker-chosen product page into a fresh tab to keep the shopper engaged, while the original tab takes a quick, unnoticed round-trip through the attacker's affiliate tracking link and back to the shop, to plant the attacker’s attribution cookie in the background. Console masking and self-defending source checks make inspection harder, while the cooldowns and narrow schedules limit how often the malicious path can appear during otherwise normal shopping. The following sanitized excerpt shows how the payload hooks dynamic product tiles and executes the dual-tab detour. We simplified identifiers, reformatted the code, and neutralized destination URLs for readability . // Watch for late-rendering product elements and hook clicks new MutationObserver , observer = { const tile = document.querySelector TARGET SELECTOR ; if tile return; observer.disconnect ; tile.addEventListener "click", e = { // Bail out if cooldown is still active on this device const stored = JSON.parse localStorage.getItem STORAGE KEY || "null" ; if stored && stored.expires Date.now return; e.preventDefault ; e.stopPropagation ; localStorage.setItem STORAGE KEY, JSON.stringify { value: "tracked", expires: Date.now + COOLDOWN MS } , ; // Keep shopper engaged in new tab... window.open target.link, " blank" ; // ... while routing original tab through the attacker's affiliate link setTimeout = { window.location.href = target.redirectUrl; }, 200 ; } ; // Note: some variants added { once: true } to detach after the first tap } .observe document.body, { childList: true, subtree: true } ; The paused builds showed how the campaign could go dark without removing the script. Their embedded configuration set status: "paused" , so they exited before installing click handlers. These paused scripts carried different per-shopper cooldown configurations 3, 4, and 5 days . One of the paused scripts even recorded a version-history comment explicitly documenting that the campaign was paused after Black Friday. To reach visitors in the first place, the operation leveraged the site's marketing supply chain: the third-party scripts and tag managers embedded by e-commerce sites to track ad campaigns and analytics. One confirmed delivery path ran through two otherwise ordinary tag managers: Google Tag Manager → another tag manager → malicious script. That is how the payload reached the browser, not proof that either tag manager was compromised. The attacker even disguised the domain hosting the script to pass a quick marketing review. One delivery host hid in plain sight: adtargett . com differed by a single “t” from adtarget . com , an advertising domain registered in 1998. The lookalike was registered in 2025 and, when we checked, its homepage called itself “ Adtarget.com http://Adtarget.com - Performance Marketing Agency.” This is typosquatting: by mimicking a real ad agency, the host blended in with routine marketing tags, quietly serving the malicious payload that hijacked shopper clicks and redirected them through affiliate payout links. Operation 2: The clickless affiliate theft While the first scam still needed a click, this one requires even less. A shopper can open a booking page, linger over the product options, and never touch an ad. In the background, however, the script might have already sent an affiliate request that could make a later sale look as though someone else had referred the shopper. Indeed, when the script’s conditions are met, the payload sends that request through a hidden iframe or a link that clicks itself. What the shop lost For the affected tourism business, the attack could corrupt the economics of customer acquisition: a legitimate booking or purchase could be credited to an unearned affiliate account. The code proves covert, automated affiliate requests, but whether any specific request resulted in completed attribution, account crediting, or paid commission in practice remains unobserved. Attack chain Time-gated browser → covert affiliate request off-screen iframe → 1-hour throttle cookie → when blocked, automated hidden-link click fallback How it stayed hidden The script conceals the affiliate request in two layers: selective execution a pre-flight network gate and hourly schedule , and stealth delivery an off-screen iframe . The first layer is surprising because its country labels are disconnected from actual geography: neither the shopper’s nor the shop’s location drives the choice. First, the script calls a public IP-based geolocation service but ignores everything it returns, including the shopper’s country. We could not determine why it required a successful response while ignoring the returned data; this may have been intended to confuse investigators or simply been a remnant of an earlier version. Interestingly, if the geolocation request fails, the script silently stops; its promise chain ends with .catch = {} . Although intent is unproven, this fail-closed behavior could help the script evade network-restricted sandboxes. Next, instead of using the fetched geolocation data, the payload contains three TradeDoubler an affiliate-marketing network configuration objects labelled { AU , US , and UK }. These settings blocks are embedded in the code, and each contains an affiliate URL and start and end times. The script computes Asia/Kolkata time in JavaScript, checks those configured time windows, then applies fixed odd/even-hour rules to choose one of the three or else skip the affiliate request for that run. The choice is deterministic. Together, the schedule and browser-state checks create time-gated selective execution, a form of cloaking. When those conditions do not line up, the affiliate behavior stays dormant, so a one-off inspection can miss it. Once the script chooses a configuration, it writes a local cookie named affiliateClicked