AppsFlyer Web SDK served crypto-stealing JavaScript after a domain registrar incident

AppsFlyer's Web SDK domain served wallet-swapping JavaScript in March 2026. How the payload worked, who was exposed and how to defend third-party scripts.

TechLogHub Engineering Team
March 14, 2026
4 min read
0 views

Share Article

AppsFlyer Web SDK hijacked to spread crypto‑stealing JavaScript code

For several hours on 9–10 March 2026, websites loading AppsFlyer's Web SDK from websdk.appsflyer.com served attacker-controlled JavaScript that swapped cryptocurrency wallet addresses. AppsFlyer attributed it to a "domain registrar incident." The case is a clear reminder that every <script src> pointing at a third-party domain gives that domain, and whoever controls its DNS, full control of your page.

What happened

Incident response firm Profero began investigating on 9 March after customer reports. It confirmed obfuscated malicious code being served from AppsFlyer's official Web SDK domain alongside the legitimate SDK. Profero put the start of the window at about 22:45 UTC on 9 March and said it could not confirm when it ended (possibly as late as 11 March). A Cloud Security Alliance research note, drawing on community analysis, estimated a shorter window of roughly 14 hours ending around 10:30 UTC on 10 March.

AppsFlyer said it "detected and contained a domain registrar incident on March 10" that exposed the Web SDK "running on a segment of customer websites to unauthorized code." It said the mobile SDK was not affected and that it had found no evidence that customer data on AppsFlyer systems was accessed. According to CSA, AppsFlyer also revoked API V2 tokens issued before 19:00 UTC on 10 March. AppsFlyer says about 15,000 businesses use its platform across more than 100,000 apps.

Researchers described the payload as follows:

  • It kept the SDK's analytics working so nothing looked broken.
  • It decoded obfuscated strings at runtime and wrapped fetch and XMLHttpRequest to inspect and rewrite traffic.
  • It used a MutationObserver and clipboard hooks to find wallet addresses for Bitcoin, Ethereum, Solana, XRP and TRON and replace them with attacker addresses.
  • It fetched current attacker addresses from /v1/api/plugin and sent the original address, page URL, timestamp and user agent to /v1/api/process, both on the compromised domain.

Who is affected

  • Websites and web apps that load the AppsFlyer Web SDK dynamically from websdk.appsflyer.com during the window. Self-hosted or bundled copies weren't affected.
  • Their end users, especially anyone who typed, pasted or was shown a crypto wallet address on those pages.
  • AppsFlyer API V2 token holders, who needed to regenerate tokens.

No company has publicly confirmed financial losses.

What it means for developers and engineering teams

Most supply-chain defences, such as lockfiles, signed packages and SBOMs, protect code you build. A runtime-loaded script skips all of them. If the vendor's DNS, registrar account, CDN or TLS certificate is compromised, the attacker serves new code straight to your users, and your build pipeline never sees it. The 2024 polyfill.io incident followed the same pattern.

The payload also shows why a strict Content-Security-Policy that only allowlists the vendor's domain isn't enough here. Exfiltration and command-and-control went through the same trusted domain, so connect-src allowlisting didn't help. What does help is pinning the exact code (Subresource Integrity or self-hosting), and keeping marketing and analytics tags off sensitive pages entirely.

The incident also exposes a practical gap in monitoring. A third-party script that keeps working normally while adding hidden behaviour won't trip error-rate alerts or synthetic uptime checks. Detecting it needs either integrity checks (compare the served file hash against a known-good baseline on a schedule) or behavioural monitoring in the browser, such as watching for new network destinations or for scripts wrapping fetch. PCI DSS 4.0.1 requirements 6.4.3 and 11.6.1 already ask payment pages to inventory scripts and detect unauthorised changes, and that is a sensible baseline for any page that handles money or credentials.

What to do now

  1. Inventory third-party scripts on every page, and find out which load from a vendor domain at runtime.
  2. Pin versions and add SRI where the vendor publishes versioned files: <script src="…/sdk-1.2.3.js" integrity="sha384-…" crossorigin="anonymous">. Generate the hash with openssl dgst -sha384 -binary sdk.js | openssl base64 -A.
  3. Self-host or proxy critical SDKs through your own build, so updates go through code review.
  4. Keep analytics and marketing tags off checkout, wallet, login and settings pages.
  5. Use CSP with reporting (report-to) to catch unexpected script sources and eval use. Consider require-trusted-types-for 'script'.
  6. If you used AppsFlyer's Web SDK, search logs and RUM data for /v1/api/plugin and /v1/api/process requests on 9–11 March, regenerate API tokens, and check with counsel whether users who handled wallet addresses need to be notified.

Related on TechLogHub

Sources

Stay Updated

Get the next deep dive in your inbox

Subscribe for product analysis, engineering explainers, and practical guides published on TechLogHub.

See what launched this week

One email a week: new and trending developer tools, fresh comparisons, and what shipped. Unsubscribe in one click.