Togoder security

npm package security report

rolldown@1.2.11 security report

Risky patterns found that deserve a look.

Needs review Version 1.2.11 Files reviewed 30 Size 529.0 KB Scanned

Summary

Togoder Security scanned the npm package rolldown@1.2.11 on Oct 6, 2026. An AI review of 30 source files produced 2 high, 9 medium, 13 low severity findings. The overall verdict is medium: the findings flag risky but common patterns (dynamic code, unsafe defaults, broad file or network access) rather than confirmed malware.

0
critical
2
high
9
medium
13
low

Findings 24

high

Dynamic import with external input

NPS-CB4CA2815594

The HMR update handler calls import(data.path) using the path field from a WebSocket message. If the WebSocket server (ws://$ADDR) is compromised or spoofed, this allows arbitrary module loading/execution from attacker-controlled paths. This is a dynamic import with computed/external input.

dist/experimental-default-runtime.mjs:88
high

Remote script injection

NPS-F2A43036C59C

In non-Node environments, loadScript(data.url) creates and appends a <script> element with src from the WebSocket message, executing remotely-supplied JavaScript. Combined with the insecure ws:// scheme (not wss://), this enables remote code execution via MITM or hostile server.

dist/experimental-default-runtime.mjs:91
medium

Insecure WebSocket connection

NPS-0697663D6906

The WebSocket is established over unencrypted ws:// (line 66: new URL('ws://$ADDR')), allowing network attackers to intercept or inject HMR messages (including hmr:update payloads) leading to code execution.

dist/experimental-default-runtime.mjs:66
medium

Code execution via runtime message handling

NPS-C9AE3FBEA6F0

Top-level code establishes a WebSocket listener that executes server-controlled module paths/URLs on receipt of hmr:update messages. While typical for HMR runtimes, the lack of origin/authentication validation makes this a powerful code-execution primitive.

dist/experimental-default-runtime.mjs:83
medium

Dynamic import with computed input

NPS-77EA1506F366

The code dynamically imports a module using pluginInfo.fileUrl, which comes from workerData. This value is passed to the worker thread from the parent process and is not validated or restricted within this file. If an attacker can control workerData, they could load and execute arbitrary code.

dist/parallel-plugin-worker.mjs:8
medium

Network download and package installation at runtime

NPS-29E3D70A3BD2

The webcontainer fallback path, when running inside a WebContainer environment, deletes /tmp/rolldown-<version>, recreates it, and executes pnpm i @rolldown/binding-wasm32-wasi@<version> via childProcess.execFileSync to download and install a package from the registry at runtime. While this is a known fallback mechanism for WebContainer environments and uses the package manager rather than direct curl/wget, it performs network fetch and process spawning triggered by top-level/import-time code, which is a supply-chain risk if the registry entry is compromised.

dist/shared/binding-BY0qR5iS.mjs
medium

Dynamic module loading with environment variable path

NPS-ECF18A27274C

If process.env.NAPI_RS_NATIVE_LIBRARY_PATH is set, the code calls __require(process.env.NAPI_RS_NATIVE_LIBRARY_PATH) to load an arbitrary native module. This allows an attacker who can set that environment variable (or a malicious CI/dev environment) to load arbitrary code. This is an intentional escape hatch but is a risky pattern because it trusts an env var to specify a module path.

dist/shared/binding-BY0qR5iS.mjs
medium

Module hook registration at import time

NPS-1C7F69324815

createOnThreadImporter() calls Module.registerHooks({ resolve }) at module load time (when createImporter() is first invoked). Module hooks allow interception and rewriting of all import resolutions in the process, which is a powerful capability that could be abused. The code propagates tracking queries through the resolve hook, mutating result.url in place for relative file imports.

dist/shared/dist-DKbukT1H.mjs:84
medium

Dynamic module loading with computed input

NPS-C15354C36C7A

The freshImport() function dynamically imports modules using a computed specifier built at runtime (specifier + formatTrackingQuery(...)). This pattern caches-busts Node's module cache and re-evaluates modules in a fresh graph. While this is the intended functionality of the 'fresh-import' package, dynamic imports with computed input can be abused to execute arbitrary code if the specifier is attacker-controlled.

dist/shared/dist-DKbukT1H.mjs:96
medium

Dynamic code import and execution

NPS-592DFA152D7E

The module dynamically imports JS/TS config files specified by the user and executes them. It also bundles TS configs via rolldown and writes the bundled output next to the original config file before importing it. While this is a legitimate config-loading feature used by Rolldown, it involves executing arbitrary code from config files and creating temporary files on disk.

dist/shared/load-config-iYtRcbXn.mjs
medium

Dynamic code execution

NPS-E3F7C0B8221C

The code uses new Function(...) inside createMerger(fnCount) to dynamically construct a function body from generated strings. Although the input fnCount is derived from the number of visitor functions (internal count, not directly attacker-controlled), this pattern is a dynamic code generation red flag. It is part of the legitimate oxc-parser visitor optimization, but it is worth noting.

dist/utils-index.mjs:1089
low

Module compile cache manipulation

NPS-9E6EEFC0920C

The code uses module.enableCompileCache and module.flushCompileCache. These are experimental Node.js features that cache compiled JavaScript modules. While not inherently malicious, they can be used to persist code execution artifacts on disk and may be abused to load cached malicious code across runs. The try/catch blocks suppress errors, which is common but can hide failures.

bin/cli.mjs:3
low

Dynamic import

NPS-2F44B3AFD7CF

The file dynamically imports '../dist/cli.mjs' at the top level. While the path is static and relative, dynamic imports can be used to execute code that is not statically analyzable. This is a common pattern for CLI tools, but it is worth noting as it runs code at import time.

bin/cli.mjs:10
low

Top-level async execution

NPS-651352286B35

The code executes an async IIFE immediately on module import, registering plugins and communicating with the parent thread. This is expected for a worker entry point, but it runs automatically without any guard, which could be abused if the module is imported in an unexpected context.

dist/parallel-plugin-worker.mjs:6
low

Potential error information exposure

NPS-14034D7277FA

The catch block posts the entire error object to the parent thread. Depending on the nature of the error, this could leak sensitive internal details (e.g., stack traces, file paths) to the parent process.

dist/parallel-plugin-worker.mjs:16
low

Process spawning and shell command execution

NPS-4D5E2DCA2AE3

Uses child_process.execFileSync('pnpm', ['i', bindingPkg]) to install a package, and child_process.execSync('ldd --version') to detect musl libc. These are process-spawning operations, though the arguments are not derived from untrusted external input and are part of standard native binding loading logic.

dist/shared/binding-BY0qR5iS.mjs
low

File system manipulation outside package scope

NPS-9F8415D2DDA2

In the WebContainer fallback, the code performs fs.rmSync(baseDir, {recursive: true, force: true}) and fs.mkdirSync(baseDir, {recursive: true}) on /tmp/rolldown-<version>, which is outside the package directory. This is confined to a versioned tmp directory but still writes/removes files outside package scope.

dist/shared/binding-BY0qR5iS.mjs
low

Dynamic requires with computed/platform-specific specifiers

NPS-117A09F4C043

Numerous __require calls use dynamic platform/arch-derived specifiers (e.g., @rolldown/binding-linux-x64-gnu) and optional dependency loading. This is standard napi-rs binding loader behavior, but the pattern of resolving and loading many native .node binaries at import time is a supply-chain risk if any optional dependency is hijacked.

dist/shared/binding-BY0qR5iS.mjs
low

filesystem-read

NPS-558A02E78BA9

getDefaultDevRuntime reads runtime files via fs.readFileSync and fileURLToPath(import.meta.resolve(...)), but these paths are hardcoded package-internal runtime entries, not attacker-controlled or credential files.

dist/shared/bindingify-input-options-XrReX_BJ.mjs
low

filesystem-operations

NPS-F90165C3772C

A fsModule object exposes common async fs operations (readFile, writeFile, unlink, etc.) to plugin contexts. This is standard bundler plugin API surface for user-authored plugins, not autonomous package-install behavior.

dist/shared/bindingify-input-options-XrReX_BJ.mjs
low

import-time-execution

NPS-8ACEFC7C45A3

Top-level code includes Object.defineProperty patches on BindingMagicString.prototype and __decorate/lazyProp setup. These are local prototype enhancements within the package and do not perform network access, credential harvesting, or shell execution.

dist/shared/bindingify-input-options-XrReX_BJ.mjs
low

Dynamic string construction from runtime input

NPS-0BD94FDBC3F1

buildQueryRE() builds a RegExp from queryName using escapeRegExp; escapeRegExp is properly implemented to escape regex metacharacters, so regex injection is mitigated. formatTrackingQuery() concatenates runtime values into a URL query. No direct injection risk given upstream handling, but flagged for review.

dist/shared/dist-DKbukT1H.mjs:18
low

Data URL code execution via Module.register

NPS-9BB06141E26F

loader_default is a data:text/javascript URL containing an embedded payload registered via Module.register() in a worker thread. While the payload is not obfuscated or encrypted (it is readable source), using a data URL as an ESM loader is an unconventional mechanism that evades normal file-based source review and could disguise malicious intent in modified versions.

dist/shared/dist-DKbukT1H.mjs:70
low

File system manipulation outside package scope

NPS-086994C197C3

bundleTsConfig writes a generated bundle file (with inline sourcemap) into the directory containing the user's config file and deletes it afterward. loadNativeConfig also appends a timestamp query to the import URL to bypass module caching. This is expected for a build tool's config loader but does modify the user's working directory.

dist/shared/load-config-iYtRcbXn.mjs

Files reviewed

FileVerdictWhat the reviewer saw
bin/cli.mjs medium The CLI entry point uses dynamic import and Node.js module compile cache APIs, which are legitimate but could be abused; no clear malicious behavior is evident.
dist/experimental-default-runtime.mjs medium This HMR dev runtime accepts unauthenticated WebSocket messages over plaintext ws:// and executes server-supplied module paths or script URLs, which could lead to remote code execution if the HMR server or network is compromised.
dist/parallel-plugin-worker.mjs medium The worker code dynamically imports modules from URLs provided via workerData and runs an async IIFE on import; while likely legitimate for a plugin system, the lack of validation on dynamic imports poses a moderate security risk if workerData is externally controllable.
dist/shared/binding-BY0qR5iS.mjs medium This is a standard napi-rs native binding loader for rolldown with legitimate platform-specific dynamic requires and a WebContainer fallback that downloads and installs a WASI binding package at runtime; no data exfiltration, credential harvesting, obfuscation, or backdoor patterns were detected, but runtime package installation and env-var-controlled native library loading are noteworthy supply-chain/risk surfaces.
dist/shared/dist-DKbukT1H.mjs medium The 'fresh-import' package purposefully registers ESM module hooks and performs dynamic imports with computed specifiers to re-evaluate modules in fresh graphs; while no overt malicious patterns (exfiltration, credential harvesting, backdoors, shells) are present, its powerful use of Module.registerHooks, data URL loaders, and dynamic imports warrants 'warning' risk for supply-chain review.
dist/shared/load-config-iYtRcbXn.mjs medium This is Rolldown's config loader that intentionally executes user-provided config files and bundles TypeScript configs, which is expected behavior for a build tool but involves dynamic code execution and temporary file writes.
dist/utils-index.mjs medium The file is a bundler-generated utility module for rolldown/oxc-parser AST visiting that is largely safe, with the only notable concern being a benign use of new Function for merging visitor callbacks.
dist/cli.mjs safe No malicious patterns detected; this is the legitimate Rolldown CLI bundler entrypoint with standard argument parsing and build logic.
dist/config.mjs safe The file only re-exports symbols from internal shared modules and contains no suspicious or malicious patterns.
dist/experimental-index.mjs safe No malicious patterns detected in this rolldown experimental API barrel file; all imports are internal relative modules and the logic handles bundler/dev-engine configuration without exfiltration, credential harvesting, obfuscation, or process spawning.
dist/experimental-runtime-base.mjs safe This file contains only standard esbuild/CommonJS/ESM interop helper functions and a base64-to-binary decoder with no network, filesystem, process, or dynamic code execution behavior.
dist/experimental-runtime.mjs safe No malicious patterns detected; this is a module runtime implementation with no network, filesystem, process, or dynamic code execution behavior.
dist/filter-index.mjs safe No malicious patterns detected; the file contains legitimate plugin filtering and filter-expression utilities for Rolldown/Vite with no data exfiltration, credential harvesting, obfuscation, dynamic execution, or process spawning.
dist/get-log-filter.mjs safe Cleared by Jev triage; no further analysis needed
dist/index.mjs safe No malicious patterns detected
dist/parallel-plugin.mjs safe No malicious patterns detected
dist/parse-ast-index.mjs safe No malicious patterns detected; the code is a straightforward AST parsing utility with no network, filesystem, process, or dynamic execution behavior.
dist/plugins-index.mjs safe No malicious patterns detected; the file only exports a benign Rolldown builtin replace plugin and an esm external require plugin with no network, filesystem, process, or dynamic code execution behavior.
dist/shared/bindingify-input-options-XrReX_BJ.mjs safe This is a legitimate Rolldown bundler internal module that wires plugin hooks, lazy properties, and binding APIs without any malicious exfiltration, credential access, shell spawning, or obfuscated payloads.
dist/shared/constructors-xEvVj3lN.mjs safe No malicious patterns detected; the code only defines Vite/Rolldown builtin plugin constructors with no network, filesystem, process, or dynamic execution behavior.
dist/shared/define-config-Demdg3_4.mjs safe No malicious patterns detected
dist/shared/error-C7pxws0W.mjs safe No malicious patterns detected; the file contains only sourcemap type helpers and error normalization utilities for a build tool.
dist/shared/logs-D6uA606S.mjs safe No malicious patterns detected; the file contains only local error/logging and code-frame utilities with no network, filesystem, process, or dynamic-execution behavior.
dist/shared/misc-DOSKtd97.mjs safe This file contains only standard utility functions (array coercion, promise detection, error throwers, noop, and path fragment validation) with no malicious patterns such as network calls, credential harvesting, obfuscation, or dynamic execution.
dist/shared/normalize-string-or-regex-F14uvr6D.mjs safe The code is a utility module for a Vite/Rolldown plugin system with no malicious patterns detected.
Show 5 more files
FileVerdictWhat the reviewer saw
dist/shared/parse-WKtEKiA6.mjs safe The file is a JavaScript parser wrapper around a native Rust binding (oxc-parser) that parses JS/TS ASTs; no exfiltration, credential harvesting, obfuscation, network, process, or filesystem abuse patterns were detected.
dist/shared/prompt-CH6TK0bC.mjs safe This is a bundled consola prompt module that uses only standard Node.js APIs for terminal UI rendering with no malicious patterns detected.
dist/shared/resolve-tsconfig-DHwpIs5e.mjs safe No malicious patterns detected; the code is a legitimate TypeScript/JavaScript transformation wrapper that delegates to a native binding.
dist/shared/rolldown-CgWItHdG.mjs safe No malicious patterns detected; the code is a standard Rolldown bundler API wrapper with no data exfiltration, credential harvesting, obfuscation, or unauthorized system access.
dist/shared/watch-DUTFlQ6u.mjs safe This file is a legitimate bundler watcher module (Rolldown) that manages signal handling and file watch events without any malicious patterns.

Frequently asked questions

Is rolldown safe to use?

No confirmed malware was found in rolldown@1.2.11, but the review flagged 2 high, 9 medium, 13 low severity findings for risky patterns worth checking before you rely on it.

Does rolldown contain malware?

No malware was identified in rolldown@1.2.11 when Togoder Security scanned it on Oct 6, 2026. A new version can still introduce malicious code, so scan the exact versions in your lockfile.

How was rolldown checked?

Togoder Security downloaded the published npm package and had an AI model read its 30 source files, looking for install scripts, credential access, network exfiltration, obfuscation, backdoors and crypto-wallet theft. The results are cached by file hash and shown here.

How do I scan rolldown together with the rest of my dependencies?

Upload your lockfile at https://security.togoder.click/scan or call the API documented at https://security.togoder.click/api-docs. Files that have already been scanned, like the ones in rolldown@1.2.11, cost nothing.

Related security reports