Browser-Assembled Malware: SourTrade Breaks Hash Detection
Confiant's SourTrade campaign ships malware in pieces and lets the browser build the executable in memory. Browser-assembled malware gives every victim a unique hash.
Almost every detection control in your stack answers a question about a file. Is this hash known bad? Is this binary signed? Has this artifact been seen before, anywhere, by anyone? That model has held up for thirty years because it rested on one quiet assumption: at some point, the malware exists as a file, and at some point that file crosses a boundary you can inspect.
On 23 July 2026, ad-security firm Confiant published its analysis of a malvertising cluster it tracks as SourTrade, and the assumption does not survive it. The campaign never ships a malicious executable. It ships a clean one, plus a recipe, and makes the victim's browser do the assembly. BleepingComputer and The Hacker News both picked it up on 25 July. Michael Steele, of Confiant's threat intelligence team, put the consequence in one sentence:
"No finished malware ever exists on the network."
That is not a marketing line. It is a precise statement about where your inspection points are, and it deserves to be taken literally.
How browser-assembled malware is built, stage by stage
The delivery chain has four stages, and none of them individually looks like an attack.
Stage 1 — the download manager. The landing page (reached through a paid ad impersonating TradingView, Solana or Luno) registers a ServiceWorker at /sw.js. The worker's job is not persistence in the malware sense — it is to intercept same-origin fetches and hold an in-memory download stream. The page also instantiates a SharedWorker from JavaScript embedded directly in the page, avoiding a separate script fetch that a scanner might follow.
Stage 2 — the recipe. The SharedWorker calls /config. The server does not return a payload. It returns build instructions: a session-specific random seed, a size value, a standaloneUrl, and a template array describing byte-copy operations.
Stage 3 — assembly in the victim's browser. The browser fetches and gunzips a clean, legitimate Bun runtime from standaloneUrl — a second domain, unrelated to the landing page. It then generates a per-victim pseudorandom stream with AES-CTR from the server-supplied seed, and walks the template, splicing together four ingredients:
- the clean Bun interpreter engine
- a delivered PE header and section table
- the locally generated pseudorandom bytes
- an actor-controlled
.bunPE section carrying malicious JavaScriptCore bytecode
Bun's own --compile design — embed bytecode in a .bun section of a standalone runtime — is what makes this possible. The attacker is not defeating the runtime; they are using it exactly as documented, with their own bytecode.
Stage 4 — same-origin delivery. The assembled stream is handed to the ServiceWorker and a hidden iframe navigates to a same-origin URL, triggering a download with a generic binary content-type. Because the ServiceWorker served it, the Mark of the Web recorded in the file's Zone.Identifier alternate data stream names the landing page as the source. The remote component host never appears in the provenance record. Confiant notes earlier variants used the public StreamSaver project on GitHub; the switch to same-origin ServiceWorker delivery happened after April 2026, and it exists specifically to clean up that provenance trail.
Why browser-assembled malware breaks hash-based detection
Work through what each control actually gets to see.
| Control | What it observes | Verdict |
|---|---|---|
| Network AV / TLS inspection | A gzipped, legitimate Bun runtime from an unfamiliar host | Clean — because it is clean |
| Hash / IOC feed | A file it has literally never seen, and never will again | No match |
| Sandbox detonation of the landing page | A blank page, if the cloaker fingerprints you as a scanner | Nothing |
| MotW / provenance review | Landing-page domain as origin | Consistent, and wrong |
| SmartScreen / reputation | An unsigned binary with zero reputation | Fires |
| Egress behaviour analysis | The full multi-host fetch-and-assemble sequence | Visible |
The AES-CTR step is the load-bearing one. It means every victim receives a byte-different executable, so a hash is a fact about one infection and nothing more. Confiant is blunt about it: "Each victim can receive a different assembled file, which limits the value of simple hash-based detections."
The cloaking kit closes the other door. Analysts, scanners and security bots get routed to blank pages; only fingerprinted victims see the brand replica. So the two cheapest ways to get a verdict — submit the hash, detonate the URL — both return nothing, and both return nothing silently, which is the worse failure mode. A "clean" verdict from a control that was never shown the artifact reads identically to a real one.
Two things do still work, and they are worth naming because the reflex is to assume nothing does. Reputation-based endpoint controls bite harder here, not less: a per-session-unique, unsigned PE has zero reputation by construction, which is exactly what SmartScreen and equivalent controls are built to flag. And the network sequence — ad referral, cloaked landing, /config with seed and size, a large gzipped runtime pulled from a different domain, then a same-origin download — is a shape, and the shape is identical across all 90-plus domains in Confiant's IOC set.
The lineage: JSCEAL, WeevilProxy, and 35,000 ads
SourTrade is a delivery cluster, not a new payload. The malware it builds overlaps with what Check Point tracks as JSCEAL and WithSecure calls WeevilProxy — a family that installs a local proxy to intercept traffic, harvests browser cookies and stored passwords, logs keystrokes, captures screenshots, and drains cryptocurrency wallets.
The scale is documented. Check Point Research traced the campaign to March 2024 and counted, between January and June 2025, over 35,000 malicious ads served inside the European Union alone, generating an estimated 3.5 million impressions, impersonating close to 50 cryptocurrency trading applications. Check Point's own summary put likely global exposure above 10 million users. Bitdefender's 2025 analysis of the same payload family, referenced by BleepingComputer, documented the proxy-interception and wallet-theft behaviour.
Confiant's current targeting spans 12 countries — Japan, Thailand, South Korea, Taiwan, Hong Kong, Bolivia, Brazil, Nigeria, Turkey, South Africa, Australia and Great Britain — with localised ad creative for each. The landing pages carry Google Ads conversion logic, Meta pixels and X/Twitter event tracking, which tells you something uncomfortable: the operators are A/B testing victim acquisition across three major ad ecosystems with the same instrumentation a growth team would use.
This is a consumer-facing crypto campaign today. The technique is not consumer-specific. Nothing in the four stages depends on the lure being a trading app, and nothing depends on the payload being an infostealer.
Remediation
There is no patch here — no CVE, no fixed version. The affected component is the assumption that a file has a stable identity. What follows is the runbook.
1. Am I affected?
Start with provenance, not hashes. Every downloaded executable carries a Zone.Identifier alternate data stream recording where the browser believed it came from:
Get-ChildItem C:\Users\*\Downloads\*.exe -Force |
ForEach-Object {
$z = Get-Content $_.FullName -Stream Zone.Identifier -ErrorAction SilentlyContinue
if ($z) { [PSCustomObject]@{ File = $_.FullName; Zone = ($z -join '; ') } }
}
Look at HostUrl and ReferrerUrl. In this campaign they will name a plausible-looking brand-replica domain on .digital, .info, .club or .site — and, because of the same-origin trick, they will agree with each other. That internal consistency is the tell, not an inconsistency.
Then check the proxy and DNS logs for the sequence, not the destinations:
- a
GET /config(or equivalent JSON build-instruction fetch) to a recently registered domain - within the same browser session, a large gzipped binary fetch from a different host
- a subsequent same-origin download of an
application/octet-streamfrom the first host
Any two of the three in one session is worth a look. All three is an incident.
2. There is no patch — remove the delivery path instead
- Browser download policy. Chrome and Edge both expose
DownloadRestrictions; set it to block dangerous or all executable downloads for standard user populations. This is the single highest-yield control against the entire technique class. - Application control. WDAC or AppLocker rules that block unsigned or signature-invalid PEs executing from
%USERPROFILE%\Downloadsand%LOCALAPPDATA%\Tempstop the assembled binary regardless of what it contains. Assembly invalidates any signature the clean runtime carried. - Keep reputation controls on. SmartScreen and equivalents are the one endpoint control the per-session-unique hash makes stronger. Do not let a "too many prompts" ticket turn it off.
- Ad-layer blocking at DNS. Not a panacea, but the initial referral is a paid ad. Blocking ad-tech resolution on managed endpoints removes stage zero.
3. Can't change browser policy right now?
Block the newly registered TLD patterns the campaign favours at the resolver, alert on any endpoint fetching a gzipped binary larger than a few megabytes from a domain with no organisational history, and — for finance, treasury and crypto-adjacent teams specifically — push a targeted advisory that trading and wallet software is installed from vendor sites only, never from a sponsored search result.
4. Hunt for compromise
Confiant published three payload SHA-256 hashes and more than 90 malvertising domains. Use them, but understand what they are: the hashes identify three specific assemblies and will not match a fourth victim. The domains age out.
Behavioural signals are the durable ones:
| Observed behaviour | ATT&CK |
|---|---|
| Paid ad as initial access vector | T1583.008 Malvertising |
| Cloaked landing page delivering the chain | T1189 Drive-by Compromise |
| Clean runtime pulled as a build component | T1105 Ingress Tool Transfer |
Bytecode in .bun section, AES-CTR filler |
T1027 Obfuscated Files or Information |
| Client-side assembly of the final PE | T1140 Deobfuscate/Decode Files or Information |
| MotW provenance rewritten to same-origin | T1553.005 (closest mapping) |
| User runs the assembled installer | T1204.002 User Execution: Malicious File |
| Local proxy for traffic interception | T1090 Proxy |
| Keylogging, screenshots | T1056.001, T1113 |
| Browser credential and cookie theft | T1555.003, T1539 |
| Exfiltration to operator infrastructure | T1041 |
On the endpoint, hunt for ServiceWorker registrations on domains no business process should touch, and for Bun-derived processes running from user-writable paths where no developer tooling is deployed.
5. Eradicate and verify
Removing the binary is the easy half. The payload's product is credentials and live sessions, so eradication is not complete until you:
- revoke active sessions and refresh tokens for every identity used on the host — session revocation is a separate action from a password reset in Entra ID, so do both
- reset every credential stored in the affected browser profiles, personal ones included, because the harvester does not respect the corporate boundary
- treat any cryptocurrency wallet touched from that host as compromised and move funds to a key generated elsewhere
- audit for local proxy configuration and installed root certificates left behind by the interception component
- review mailbox rules, OAuth grants and MFA registrations created during and after the intrusion window
Verify after revocation, not before: re-authentication attempts with the old tokens from unfamiliar networks are the confirmation that the stolen sessions were live and are now dead.
Detecting what has no stable identity
The honest reading of SourTrade is that the industry's default detection primitive — the hash — has been engineered around, cheaply, using documented browser APIs and a legitimate runtime. Every IOC in Confiant's report is accurate, useful, and disposable. The operators can rotate all 90-plus domains this week and change nothing about how the technique works.
What they cannot rotate is the shape of the traffic. The chain must fetch the recipe, must pull a large runtime from a second host, must deliver same-origin, and — once running — must proxy, beacon and exfiltrate. This is the case Zero Hunt's AI Traffic Analysis is built for: a proprietary deep-learning model trained on billions of PCAP sequences, with four parallel inference heads — suspicious traffic, malware classification, attack type identification, and application fingerprinting — running on the appliance GPU, on-premise, with no cloud callback. The application-fingerprinting head is the relevant one here: it does not ask whether a destination is on a blocklist, it asks what a session is. A managed workstation pulling a compressed JavaScript runtime from a domain with no organisational history, moments after an ad referral, is a fingerprintable event whether or not anything in that transfer is malicious — and it is the same event on every one of those 90-plus domains.
The second half is proving your own controls hold. Most teams have DownloadRestrictions in a policy document and application control in a pilot ring, and no evidence about what happens on a real endpoint today. Zero Hunt's 10-agent generative pentest swarm answers that empirically — the Web, Exploit and Post-Exploit agents run a per-environment chain inside an ephemeral, gVisor-hardened container and report whether the path worked here, with every finding ECDSA-signed and change-triggered campaigns re-running when the environment shifts.
You cannot hash a file that is different for every victim. You can absolutely recognise the sequence that builds it.
If you want to see what that looks like against your own egress, get in touch — or read how the platform is put together.