Multiple espionage groups have deployed a shared modular exploit kit called BlueMoon that chains two Chromium browser flaws for remote code execution and sandbox escape with a Windows local privilege escalation. Observed in spearphishing since August 28 and September 1st, the kit was used against NGOs, aerospace and defense firms, and manufacturers. Three CVEs are chained, with one Windows flaw suspected to have been exploited since 2025.
How the chain fits together
The kit links browser initial access to local system elevation. According to researcher analysis, the maintainers watch for public Chromium corrections ahead of stable Chrome releases, study the code differences, and build working exploits aimed at users still on downstream builds.
The three issues combined in BlueMoon are:
CVE-2026-85046: type-confusion flaw in Chrome's V8 JavaScript engine that provides arbitrary memory access inside the V8 sandboxCVE-2026-87491: V8 sandbox escape that corrupts WebAssembly metadata to run embedded shellcodeCVE-2026-85880: heap-based buffer overflow in Windows ALPC that allows local privilege escalation
The browser pair covers entry and escape from the renderer sandbox, while the Windows ALPC issue converts that constrained renderer context into elevated execution. Proofpoint described CVE-2026-85880 as a classic zero-day, suspecting it has been leveraged since 2025 and repackaged in BlueMoon.
Supporting that assessment, investigators noted the privilege-escalation module was not freshly built. Proofpoint explains the timing evidence this way: the LPE binary build stamp points to last year and looks authentic, and the exploit favors earlier Windows releases, pointing to reuse of an older capability inside the new kit.
Patch and catalog context for the first browser flaw has been published separately. The NVD entry states type confusion in V8 in Google Chrome prior to 152.0.7977.82 allowed a remote attacker to execute arbitrary code inside the sandbox via a crafted HTML page, with Chromium security severity High (NVD detail for CVE-2026-85046). A public reproduction repository characterizes it as V8 type confusion in inline Array.prototype.sort involving Maglev + Turbofan, and notes it as Chrome's 6th zero-day of 2026 (PoC repository for CVE-2026-85046). CISA added CVE-2026-85046 to its Known Exploited Vulnerabilities Catalog on September 4, 2026 based on evidence of active exploitation (CISA KEV alert).
How the attack works
Execution is staged from the renderer to survive failures and adapt to the host:
- Malicious page triggers the V8 type-confusion flaw inside a Web Worker, with up to five retries.
- Successful memory access inside the V8 sandbox leads to WebAssembly metadata corruption to escape the sandbox and run embedded shellcode.
- The implant profiles the host, then triggers the Windows ALPC heap overflow to elevate the Chrome renderer.
- Elevated code injects into Chrome's parent process to launch an operator-chosen command.
- By default that command uses
curlto store an executable, typically a malware loader, under%TEMP%and run it.
Researchers described BlueMoon as a shared modular tool that supports exploit additions and was used in distinct operations, including distinct spearphishing workflows.
Activity clusters
Reports attribute four separate deployment sets to the kit, with three described as Chinese or China-aligned.
Enterprise cybersecurity company Proofpoint saw use since August 28 in spearphishing tied to JungleBamboo (a.k.a. APT31, Violet Typhoon, APT31, Tide Castle), a threat actor associated with China. That actor, described as the first Chinese state-sponsored user of the kit observed, has previously focused on NGOs in the US, mining companies, and individual high-value targets, using the Longtale/GemStone credential stealer extension disguised as Google Gemini.
Cybersecurity and threat intelligence company Volexity saw similar activity on September 1st from a different actor it tracks as UTA0560, aimed at customers at multiple non-governmental organizations (NGOs). That operation used donation lures and led to Grimwedge, an in-memory JScript backdoor for reconnaissance, file and process management, command execution, and payload uploads.
A third set, tracked as UNK_LateNight, is linked to ShadowPad backdoor deployments on systems belonging to U.S. aerospace and defense-industrial-base companies.
A fourth set, tracked as UNK_DoubleCheck, targeted Vietnamese manufacturing firms with an in-memory Rust loader, though the final payload couldn't be retrieved for analysis.
Proofpoint anticipates broader uptake, potentially reaching financially motivated attackers in the future.
Detection and mitigation
Both firms released indicators of compromise for files and network infrastructure seen with BlueMoon. Defenders are advised to use the IOCs in both reports to block the activity early.
No patch identifiers for CVE-2026-87491 and CVE-2026-85880 were included in the supplied material. For CVE-2026-85046, prioritize updating Chrome beyond the affected 152.0.7977.82 threshold noted by NVD, and track the CISA KEV listing for federal remediation timelines.
Technical background
This section is general background on this vulnerability and attack class, not new facts about BlueMoon.
V8 type-confusion bugs occur when optimized code assumes an object has one layout while it actually has another, permitting out-of-bounds memory read/write inside the sandbox. Sandbox escapes then abuse a more privileged broker or memory-management structure — here described as WebAssembly metadata — to pivot from constrained JavaScript execution to native code. Windows ALPC heap overflows corrupt inter-process message storage to gain elevated writes, turning a medium-integrity renderer compromise into SYSTEM-level execution.
Generic illustration only — not BlueMoon-specific artifacts:
# generic illustration: confirm browser build and local temp location
google-chrome --version
echo %TEMP%
curl --version
// generic illustration: Web Worker retry wrapper pattern (not the actual exploit)
async function runWithRetries(workerUrl, attempts = 5) {
for (let i = 0; i < attempts; i++) {
try {
const w = new Worker(workerUrl);
await new Promise((res, rej) => { w.onmessage = res; w.onerror = rej; });
return true;
} catch (e) {}
}
return false;
}