# @swc/core@1.16.2 security report (npm)

- Verdict: **Needs review** (risk level: medium)
- Scanned: 2026-10-06T14:12:25.000Z
- Files reviewed: 6
- Findings: 6 medium, 7 low severity findings
- Report: https://security.togoder.click/npm/@swc/core
- Source: Togoder Security (https://security.togoder.click), AI source-code review

## Summary

Togoder Security scanned the npm package @swc/core@1.16.2 on Oct 6, 2026. An AI review of 6 source files produced 6 medium, 7 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.

## Findings

### [medium] Environment variable controlled native module loading

Finding ID: `NPS-68C2BB8FB4D4`

File: `index.js:76`

The code reads process.env['SWC_BINARY_PATH'] and, if set, loads a native Node.js addon (.node file) from that path via require(). This is a legitimate SWC feature for overriding the native binding location, but if an attacker can control this environment variable they can force the package to load an arbitrary native binary. This behavior is documented SWC functionality rather than a malicious pattern.

### [medium] Dynamic require of external/native modules

Finding ID: `NPS-8CEB5DD2243E`

File: `index.js:84`

Uses require((0, path_1.resolve)(bindingsOverride)) with a path derived from an environment variable, and falls back to require('@swc/wasm'). This is dynamic module loading based on external input (env var), which can be abused if the environment is not trusted. In the context of @swc/core this is intended behavior.

### [medium] Postinstall script execution

Finding ID: `NPS-88BB7D3B99A9`

File: `postinstall.js`

This is a postinstall script for @swc/core that runs automatically after installation. Postinstall scripts are a common attack vector for supply chain attacks, as they execute arbitrary code during package installation.

### [medium] Spawn processes/shell commands

Finding ID: `NPS-8B56C3C3B4F9`

File: `postinstall.js`

Uses child_process.execSync to run 'npm install --no-save ... @swc/wasm@${version}' during postinstall. While this appears to be a legitimate fallback mechanism for installing the WASM binary, it does execute shell commands during package installation.

### [medium] File system manipulation outside package scope

Finding ID: `NPS-77FE21ABE414`

File: `postinstall.js`

Uses fs.renameSync to move the installed @swc/wasm package into process.env.INIT_CWD/node_modules, which is outside the package's own directory. Also uses fs.mkdirSync and writeFileSync to create a temporary install directory. This modifies the user's project node_modules.

### [medium] Dynamic module loading with external input

Finding ID: `NPS-5D79C01174C1`

File: `spack.js:49`

The compileBundleOptions function dynamically requires a module based on a user-provided string (config parameter). If the string is not a local file path (does not start with './', '../', or '/'), it is passed directly to require(). This could allow loading arbitrary modules from node_modules or other resolvable paths, potentially executing malicious code if an attacker controls the config value.

### [low] Legitimate native binding loader

Finding ID: `NPS-38D6B674F503`

File: `binding.js`

This is a standard NAPI-RS auto-generated binding.js file for @swc/core. It detects platform/architecture and loads the appropriate prebuilt native .node binary, with fallback to WASI/WASM. All require() calls use static string literals targeting known platform-specific packages under the @swc scope, not computed or external input.

### [low] Filesystem read

Finding ID: `NPS-8FC74E5ED612`

File: `binding.js:36`

Reads /usr/bin/ldd to detect musl libc. Path is hardcoded, read-only, and outside package scope but only for platform detection purposes; no exfiltration.

### [low] Child process execution

Finding ID: `NPS-47DE92D808A4`

File: `binding.js:60`

Executes 'ldd --version' via child_process.execSync to detect musl vs glibc on Linux. Command is a fixed string literal with no user-controlled input; used only for platform detection, not command injection.

### [low] Environment variable read

Finding ID: `NPS-0885CAB22521`

File: `binding.js:279`

Reads NAPI_RS_FORCE_WASI environment variable solely to control WASI fallback behavior; this is benign and does not harvest credentials or secrets.

### [low] Environment variable access

Finding ID: `NPS-649DA7926224`

File: `postinstall.js`

Reads process.env.INIT_CWD and process.env.SWC_BINARY_PATH. INIT_CWD is standard for npm lifecycle scripts, and SWC_BINARY_PATH appears to be a documented override. This is not credential harvesting but does access environment state.

### [low] Dynamic module loading

Finding ID: `NPS-7CDA7D0D3713`

File: `postinstall.js`

Uses require.resolve and require with computed paths (require(path.resolve(process.env.INIT_CWD, 'package.json')), require.resolve('@swc/wasm')). While the paths are derived from package structure, dynamic resolution based on environment variables could theoretically be abused.

### [low] File system path resolution

Finding ID: `NPS-51F0A88322C2`

File: `spack.js:47`

The code resolves local file paths using path.resolve, which could access files outside the current working directory if the config parameter contains path traversal sequences like '../'. However, this is limited to requiring JavaScript modules, not arbitrary file read.

## Files reviewed

- `index.js` (medium): This is the legitimate @swc/core entry point; the only notable behavior is loading a native binding from an environment-variable-controlled path, which is intended SWC functionality but could be abused if the environment is attacker-controlled.
- `postinstall.js` (medium): This appears to be a legitimate @swc/core postinstall script that installs native bindings and falls back to @swc/wasm, but it executes shell commands and modifies files outside package scope, which are inherent risks of postinstall lifecycle scripts.
- `spack.js` (medium): The code dynamically requires a module based on a user-controlled string, which could lead to arbitrary module loading if the input is not properly validated, though it appears to be a legitimate configuration loader for a bundler.
- `Visitor.js` (safe): No malicious patterns detected; the file is a standard AST visitor class with no I/O, network, or code execution behavior.
- `binding.js` (safe): This is a benign auto-generated NAPI-RS native binding loader for @swc/core with no malicious patterns; platform detection, hardcoded module loading, and environment variable checks are all standard and safe.
- `util.js` (safe): No malicious patterns detected; the code is a standard Babel helper for wrapping native classes and contains no data exfiltration, credential harvesting, obfuscation, or process execution.

AI analysis is guidance, not a guarantee. Methodology: https://security.togoder.click/methodology
