Summary
Togoder Security scanned the npm package napi-postinstall@0.3.4 on Oct 6, 2026. An AI review of 7 source files produced 2 high, 11 medium, 6 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 19
Shell command execution with string interpolation
NPS-1484734A4435
execSync is called with a template string that interpolates pkg, version, and constants into an npm install command. If any of these values originate from an attacker-controlled package.json (e.g. a malicious dependency name/version), command injection is possible. The same pattern appears in the yarn P'n'P branch (yarn add -D ${pkg}@${version}).
Shell command execution with string interpolation
NPS-C7600FF125B5
execSync with yarn add -D ${pkg}@${version} uses interpolated values from package metadata. A crafted package name could inject shell metacharacters and execute arbitrary commands in the P'n'P environment.
Opaque downstream behavior
NPS-EA664602C314
The core logic is delegated to checkAndPreparePackage in ./index.js, which is not visible here. The safety of this CLI depends entirely on that implementation, which could contain network calls, credential harvesting, or process spawning.
Dynamic code execution via require()
NPS-9FBB457382B9
The function uses require(packageJsonPath), require(bindingEntry), and require(pkgDir) to load modules. In the WebContainer branch, bindingEntry is constructed from values read from package.json (napi.packageName, napi.binaryName, name, version). If an attacker can influence package.json contents, this could lead to loading arbitrary code from paths derived from the package metadata.
File system manipulation outside package scope
NPS-3974FD1242F3
Writes to os.tmpdir() by removing and recreating a directory named after the package (${name}-${version}) and installing dependencies there. This manipulates shared temporary storage and could overwrite or interfere with other applications' temporary files if name/version collide.
Process spawning / shell command execution
NPS-2B3AF5968949
Uses execFileSync to execute 'pnpm' (WebContainer path) and a package-manager-derived executor (npx/pnpm/yarn/bun/deno) with constructed arguments. While using execFileSync avoids shell interpolation, it still executes external binaries and could be abused if package.json fields (name, version, napi info) are attacker-controlled, allowing arbitrary package installation or execution.
Command Execution
NPS-2C7A450A31D4
Uses child_process.execSync to run 'npm config get registry', which spawns a shell command. While intended to read the npm registry configuration, this executes an external command at import/runtime. If an attacker can manipulate the environment or npm binary, this could lead to arbitrary command execution.
Dynamic Module Resolution
NPS-3D342C2A6407
Uses require.resolve(name + '/package.json') where 'name' is a parameter. If this function is called with untrusted input, it could resolve and load arbitrary packages, potentially leading to unexpected module loading or path traversal. In this context, it's likely called with a known package name, but the pattern is risky.
Command Execution
NPS-9944A3D5B15F
Uses child_process.execSync to run 'ldd --version' to detect musl libc. This spawns a shell command based on the runtime environment. The command is fixed, but it still executes an external process at import/runtime, which could be exploited if the PATH or ldd binary is compromised.
Insecure HTTP fallback
NPS-A04AC5C70AAE
fetch uses the plain http module when the URL starts with http://. This allows package downloads over an unencrypted channel, enabling man-in-the-middle tampering with the downloaded binary package.
Untrusted URL redirect following
NPS-197F538AC24F
The fetch function follows HTTP redirects (301, 302, 307, 308) to arbitrary locations without validating the destination host. A malicious or compromised NPM registry response could redirect the download to an attacker-controlled server, leading to download of a malicious tarball that is then extracted and used.
File system writes outside package scope
NPS-51C3D309757E
The install logic writes/renames files into node_modules paths resolved from require.resolve and ancestor directories (path.resolve(pkgDir, hostPkg.split('/').map(() => '..').join('/'), pkg)), potentially modifying files outside the current package's own directory tree.
Dynamic module loading / resolution
NPS-F06EC73461BA
require.resolve is invoked on computed package names derived from package.json metadata, and require(packageNameOrPackageJson + '/package.json') uses an externally supplied string. This can trigger loading of arbitrary packages specified by a malicious manifest.
Filesystem access at runtime
NPS-EC816DD39B48
The CLI reads package.json from the current working directory using fs.readFileSync. While this appears to be legitimate behavior for verifying the local package version before invoking checkAndPreparePackage, it represents filesystem access that could be abused if the downstream functions behave unexpectedly.
Top-level execution on import
NPS-A0A834FA04B4
Code executes immediately at module load time (reads process.argv and calls checkAndPreparePackage). If this module is imported rather than run as a CLI, execution still occurs, potentially triggering unintended side effects.
Environment variable manipulation
NPS-843DF9A42DDF
Sets process.env[SKIP_${name...}_FALLBACK] = '1' to bypass future fallback checks. While not inherently malicious, it modifies global process state that persists for the lifetime of the process.
Dynamic import / module cache manipulation
NPS-68C4646230F0
Deletes the resolved package path from require.cache and re-requires it. This cache-busting technique can cause re-execution of top-level module code and may be used to force reload of modified modules.
File System Access
NPS-0C088C3DDED2
Reads /usr/bin/ldd directly from the filesystem to detect musl. While not malicious per se, it accesses system files outside the package scope. This is a common pattern for native module detection but should be noted.
Environment variable access
NPS-089856F0D962
The code reads process.env and spreads it into the child process environment ({ ...process.env, npm_config_global: undefined }), and reads process.env.npm_config_user_agent. Environment contents are passed to spawned npm processes, which is standard but broadens exposure of any secrets present in the environment to the child process.
Files reviewed
| File | Verdict | What the reviewer saw |
|---|---|---|
| lib/cli.js | medium | The CLI itself shows no direct malicious code, but it performs filesystem reads and delegates core behavior to an unaudited index.js module, warranting review of the downstream implementation. |
| lib/fallback.js | medium | The code is a legitimate native-addon fallback mechanism but performs several potentially risky operations—dynamic require of computed paths, spawning package managers from metadata, and writing to shared temp directories—that could be exploited if package.json or napi metadata is attacker-controlled. |
| lib/helpers.js | medium | The code appears to be a legitimate helper module for detecting native platform targets and managing npm packages, but it uses shell command execution and dynamic module resolution that could be exploited if inputs are untrusted. |
| lib/index.js | medium | This appears to be legitimate napi binary-fetching logic, but it contains risky patterns: shell command construction via string interpolation of package metadata (command injection risk), unvalidated redirect following and HTTP fallback in downloads, and file system writes outside package scope. |
| lib/constants.js | safe | No malicious patterns detected |
| lib/target.js | safe | Cleared by Jev triage; no further analysis needed |
| lib/types.js | safe | No malicious patterns detected |
Frequently asked questions
Is napi-postinstall safe to use?
No confirmed malware was found in napi-postinstall@0.3.4, but the review flagged 2 high, 11 medium, 6 low severity findings for risky patterns worth checking before you rely on it.
Does napi-postinstall contain malware?
No malware was identified in napi-postinstall@0.3.4 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 napi-postinstall checked?
Togoder Security downloaded the published npm package and had an AI model read its 7 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 napi-postinstall 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 napi-postinstall@0.3.4, cost nothing.