Summary
Togoder Security scanned the npm package node-gyp@12.4.0 on Oct 6, 2026. An AI review of 18 source files produced 5 medium, 27 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 32
Suspicious symlink creation with external input
NPS-584998FB514B
Creates a symlink named 'python3' in a build directory pointing to the Python interpreter path read from config.gypi. The python path is taken from config.variables.python without validation. If an attacker controls config.gypi (e.g., via a malicious package or repo), they could symlink to an arbitrary executable, which is then prepended to PATH and executed during the build. This is a potential vector for code execution during build.
process_spawning
NPS-C5D163AC5423
The code spawns a child process using gyp.spawn(python, argv) to run gyp (a build tool). This is expected behavior for node-gyp, but it does execute an external process with arguments derived from configuration. No obvious injection vector is present, but spawning processes is a notable capability.
Process spawning / command execution
NPS-E0471654E994
The code uses execFile (via ./util) to spawn processes ('py.exe', 'python3', 'python', or paths derived from environment variables). On Windows, it runs commands through a shell with shell: true, which could allow command injection if environment variables are attacker-controlled (e.g., NODE_GYP_FORCE_PYTHON or PYTHON containing shell metacharacters).
Command execution with PowerShell
NPS-1C323642C54E
The code spawns PowerShell via execFile to query Visual Studio installations. While this is expected for node-gyp's VS detection, it uses '-ExecutionPolicy Unrestricted' and dynamically constructs command strings with interpolated values from environment variables (vcInstallDir, SystemRoot). The filterArg built from VCINSTALLDIR is inserted into a PowerShell command string without escaping, which could allow command injection if VCINSTALLDIR is attacker-controlled.
Path traversal risk
NPS-863D19068E7C
The version string from command-line arguments (argv[0] or gyp.opts.target) is used in path.resolve(gyp.devDir, version) before being validated. If semver.parse fails (returns null), the raw version string is used directly. While path.resolve normalizes the path, a version like '../../important-dir' would resolve outside gyp.devDir. However, the subsequent fs.stat check would need to succeed before the rm is executed, and rm is restricted to versionPath. This still constitutes a file system manipulation concern where an attacker-controlled version argument could target directories outside the intended node-gyp development directory for deletion.
Home directory access
NPS-15508FC9EF40
Uses os.homedir() to resolve '~' in --devdir and to compute cache paths via env-paths. This is normal behavior for a build tool but does access the user's home directory.
Process working directory modification
NPS-9042EA6EAE8E
process.chdir(dir) is called based on user-provided -C/--directory flag. This changes the CWD for the process which can affect subsequent file operations, but is a documented CLI behavior and validated as a directory first.
Dynamic command dispatch
NPS-533B0005AE51
prog.commands[command.name] dynamically selects and invokes a command handler based on user-supplied argument (command.name from program args). If command.name is attacker-influenced and 'commands' contains unexpected keys, this could be leveraged for unexpected invocation - though in this context it's the intended CLI dispatch mechanism, not obfuscation.
Environment variable harvesting
NPS-9515A5EDD9A2
The errorMessage() function reads and logs npm_package_name and npm_package_version environment variables. While limited to npm package metadata and only on error paths, this is a minor information disclosure pattern that could be expanded in other code paths, and it demonstrates environment variable access behavior.
Spawning processes with user-controlled input
NPS-26882B016A59
The build function spawns make or msbuild with argv that may include user-supplied options (gyp.opts.make, gyp.opts.jobs, gyp.opts.solution). While this is typical for a build tool, it allows arbitrary command execution if an attacker can influence these options, e.g., through package.json or environment variables. This is expected behavior for node-gyp but should be noted as a risk in a third-party package context.
environment_variable_modification
NPS-F189173A9F92
The code modifies process.env.PYTHONPATH and process.env.PYTHON, which could affect subsequent subprocesses. This is part of normal node-gyp operation but is a side effect that could potentially be abused in a compromised environment.
file_system_access
NPS-97EA9E421F3C
The code reads files from the node prefix directory (node_version.h) and resolves paths based on user-provided --nodedir, expanding ~ to the home directory. This is expected for node-gyp but allows reading files outside the package scope if a malicious --nodedir is provided.
dynamic_path_resolution
NPS-9168E8A765DA
The code constructs paths using user-controlled input (gyp.opts.nodedir, argv) and resolves them. While not directly malicious, it could be used to access unintended locations if an attacker controls the build arguments.
Dynamic code execution
NPS-0B99758DA292
The code uses JSON.parse on strings read from files and process.config. This is not eval or Function constructor, so it is safe, but it does parse potentially attacker-controlled config.gypi files. However, JSON.parse itself is not dangerous unless combined with eval. The parsed config is then written to a file in the build directory, which is expected behavior for node-gyp.
File system manipulation
NPS-A0C02D4FEB16
The code reads from a path derived from nodeDir and writes to buildDir. Both are expected parameters for node-gyp. No traversal outside intended directories is evident, but nodeDir could be user-controlled via --nodedir flag, potentially allowing reading arbitrary config.gypi files. This is by design for node-gyp to support custom Node.js headers.
Environment variable and credential harvesting
NPS-FF8A2F9908FA
The code accesses process.config and process.arch, but does not read environment variables or credential files like .npmrc, .ssh, etc. The gyp.opts object may contain user-provided command-line options, but these are not exfiltrated.
Network request with configurable proxy and CA
NPS-F0D023D25A60
The module downloads content from a user-supplied URL using undici fetch. Proxy and CA settings are taken from gyp options or environment variables, which is normal for node-gyp-style tooling. No data is sent to unexpected external servers; requests target the provided URL.
Environment variable usage
NPS-6E72DD774629
Reads http_proxy, HTTP_PROXY, https_proxy, HTTPS_PROXY to configure proxy support. This is expected behavior for a downloader and does not harvest credentials or secrets.
File system read
NPS-31695B56DDF3
readCAFile reads a CA certificate file from a path provided via gyp.opts.cafile. This is explicit user configuration, not harvesting of sensitive files like ~/.ssh or cloud credentials.
Environment variable harvesting
NPS-F1E18DD4E73E
The code reads numerous environment variables (USERNAME, USER, LOCALAPPDATA, SystemDrive, ProgramW6432, ProgramFiles, ProgramFiles(x86), NODE_GYP_FORCE_PYTHON, PYTHON) to construct paths and locate Python executables. While this is expected behavior for a Python finder, it could be abused to gather system/user information if the package were malicious.
File system path manipulation
NPS-795582AE76A2
The code constructs absolute file paths to Python executables across Program Files and LocalAppData directories and attempts to execute them. If an attacker can place a malicious python.exe in one of these locations, it could lead to arbitrary code execution.
Environment variable harvesting
NPS-4B2C0CDF52B2
Reads numerous environment variables including VCINSTALLDIR, VSCMD_VER, WindowsSDKVersion, and SystemRoot. These are used for VS detection logic, not exfiltration, but the pattern of environment variable access is present.
Process spawning
NPS-BA9A175C4546
Uses execFile to spawn powershell.exe with -NoProfile and various commands including Get-VSSetupInstance and Add-Type for loading a local C# file. This is standard node-gyp functionality for locating Visual Studio, but represents a shell/process execution surface.
Network download with checksum verification
NPS-A24EED0A20E0
Downloads Node.js development tarballs and Windows node.lib files from release.tarballUrl and related URLs, but verifies content against SHASUMS256.txt checksums. This is expected functionality for node-gyp's install command.
File system manipulation outside package scope
NPS-9A3CA057BB07
Creates and manages directories under gyp.devDir (typically ~/.node-gyp) and os.tmpdir(). Files are extracted from tarballs, with only .h and .gypi files filtered in. This is standard node-gyp behavior for installing dev headers.
Temp directory cleanup
NPS-D4921B82D3E4
Uses fs.rm with recursive:true on a temp directory created via mkdtemp, which is properly scoped and cleaned up in a finally block. Not a concern.
Environment variable harvesting
NPS-AD5C8C66B803
The code reads environment variables matching npm_config_* and npm_package_config_node_gyp_* and injects them into options. This is legitimate for node-gyp but could expose secrets if present in environment. However, it only reads and uses them locally, not exfiltrating.
Spawning child processes
NPS-06AB73076226
The spawn method uses childProcess.spawn to execute arbitrary commands. This is expected for node-gyp's build functionality, but could be abused if command/args are attacker-controlled. The code is part of a build tool, so this is intentional behavior.
Dynamic module loading
NPS-6EB72FD04A2E
The constructor dynamically requires command modules based on a fixed list ('./' + command). The commands are from a hardcoded array, so no user input is used for module paths. This is safe.
Spawning processes or shell commands
NPS-AA125525466C
The execFile function wraps child_process.execFile, which spawns external processes. While this is a legitimate utility used to run reg.exe for Windows registry queries, spawning processes is a red flag that warrants scrutiny.
Environment variable usage
NPS-0FAE1019A303
regGetValue reads process.env.SystemRoot to construct the path to reg.exe. This is a standard use for locating the Windows directory and is not credential harvesting, but environment variable access is noted.
File system access
NPS-873C9439218D
findAccessibleSync uses openSync to read files resolved from caller-provided candidates. This is a general-purpose file readability helper and does not target sensitive paths itself, but could be misused by callers.
Files reviewed
| File | Verdict | What the reviewer saw |
|---|---|---|
| bin/node-gyp.js | medium | The file is the legitimate node-gyp CLI entrypoint; it contains expected CLI dispatch, logging, and directory handling behaviors with no malicious exfiltration, obfuscation, or credential theft patterns. |
| lib/build.js | medium | The code appears to be a legitimate node-gyp build script with no clear malicious intent, but it creates symlinks based on unvalidated config values and spawns build commands with user-influenced arguments, posing moderate risks if the configuration is attacker-controlled. |
| lib/configure.js | medium | The code appears to be a legitimate node-gyp configure script with expected process spawning and environment modifications, but no clear malicious patterns such as data exfiltration, credential harvesting, or obfuscated code were detected. |
| lib/find-python.js | medium | This code appears to be a legitimate Python finder utility (part of node-gyp), but it spawns processes and reads many environment variables, presenting low-to-medium risk if the package or environment is compromised. |
| lib/find-visualstudio.js | medium | This appears to be legitimate node-gyp Visual Studio detection code, but it contains a potential PowerShell command injection risk via unescaped VCINSTALLDIR interpolation and spawns PowerShell with ExecutionPolicy Unrestricted. |
| lib/node-gyp.js | medium | The code is a legitimate part of node-gyp with expected build tool functionality; no malicious patterns detected, but it does read environment variables and spawn child processes as part of its normal operation. |
| lib/remove.js | medium | The remove function may allow deletion of directories outside the intended node-gyp development directory if a malicious version string containing path traversal sequences is supplied. |
| lib/util.js | medium | The code is a legitimate utility module for spawning processes and reading files, with no evidence of malicious intent, though it does contain process-spawning and file-access primitives that warrant monitoring. |
| eslint.config.js | safe | No malicious patterns detected |
| lib/clean.js | safe | No malicious patterns detected |
| lib/create-config-gypi.js | safe | The code appears to be a legitimate part of node-gyp for generating config.gypi files, with no malicious patterns such as data exfiltration, credential harvesting, or backdoor installation detected. |
| lib/download.js | safe | The code is a legitimate download helper using undici with proxy/CA configuration and contains no malicious patterns. |
| lib/find-node-directory.js | safe | Cleared by Jev triage; no further analysis needed |
| lib/install.js | safe | This is the legitimate node-gyp install.js module which downloads Node.js development files with SHA-256 checksum verification; no malicious patterns detected. |
| lib/list.js | safe | No malicious patterns detected; the code only reads and lists directory contents within the node-gyp development directory. |
| lib/log.js | safe | No malicious patterns detected |
| lib/process-release.js | safe | No malicious patterns detected; the code is a legitimate Node.js release URL resolver from node-gyp with no exfiltration, credential harvesting, obfuscation, or suspicious execution. |
| lib/rebuild.js | safe | The file is a straightforward node-gyp rebuild helper with no obfuscation, network, filesystem, or process-spawning code; it only queues clean/configure/build tasks. |
Affected version ranges
None of the 2 scanned versions of node-gyp are flagged high or critical. The latest scanned version, 13.1.0, is medium risk. Only versions we have scanned are listed; unscanned versions between them are not covered.
| Versions | Verdict | Count | Range | Top findings |
|---|---|---|---|---|
| 12.4.0 – 13.1.0 | Needs review | 2 | >=12.4.0 <=13.1.0 | process_spawning; Process spawning / command execution |
| 8.4.1 – 12.2.0 | Not scanned | 2 | >=8.4.1 <=12.2.0 |
Full list, including published versions not scanned yet: version ranges API.
Scanned versions of node-gyp
Frequently asked questions
Is node-gyp safe to use?
No confirmed malware was found in node-gyp@12.4.0, but the review flagged 5 medium, 27 low severity findings for risky patterns worth checking before you rely on it.
Does node-gyp contain malware?
No malware was identified in node-gyp@12.4.0 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 node-gyp checked?
Togoder Security downloaded the published npm package and had an AI model read its 18 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 node-gyp 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 node-gyp@12.4.0, cost nothing.