techcoff.com

How to Check an npm Package for Malware Before You Install It (2026 Guide)

how to check npm package for malware before installing guide

Learning how to check npm package for malware is now essential for every JavaScript developer. Most developers run npm install without a second thought, trusting a familiar-looking package must be safe — exactly what supply-chain attackers exploit. In October 2026, researchers exposed a malicious package called imgdecode that hid its payload inside a precompiled Windows add-on, not a visible install script. Below is a layered workflow to vet any package before it reaches your machine.

Why the Old Advice Is No Longer Enough

The October 2026 MALFEX campaign raised the bar. Per SafeDep (October 13, 2026) and The Hacker News (October 17, 2026), the imgdecode package (versions 1.0.0–1.0.3) held only a nine-line JavaScript file loading a precompiled Windows add-on, prebuilds/win32-x64/imgdecode.node. When a program called require('imgdecode') from an interactive Windows console, the add-on fetched an encrypted GitHub payload, decrypted it, and injected shellcode into dllhost.exe. It had roughly 979 downloads and was still on npm when the story broke. No single check catches everything, so you need layers.

How to Check an npm Package for Malware: The 6-Step Workflow

Step 1: Check the Metadata Before Installing Anything

To npm audit package before installing it, start with metadata — npm view costs nothing:

npm view <package-name>
npm view <package-name> maintainers
npm view <package-name> versions --json

Watch for these warning signs:

  • A brand-new maintainer or sudden ownership change, especially with a version bump.
  • A very recent publish date with little history. Attackers publish fresh packages, counting on installs before anyone reviews the code.
  • Download counts that do not match the story. Very low downloads for a supposedly popular package, or a sudden unexplained spike, both deserve questions. Counts include scanners and mirrors, so treat them as a signal, not proof.
  • Typosquatting and slopsquatting. Typosquatting is a name close to a famous package, like expres instead of express. Slopsquatting is the newer variant: fake names hallucinated by AI assistants that attackers then register for real. Verify AI-suggested names independently.
  • No repository link or README. Legitimate maintainers usually link a real repository. If the metadata already looks wrong, stop here.

Step 2: Use npm pack to Inspect the Package Without Installing It

The npm pack inspect package approach is the most valuable habit here: npm pack downloads the tarball without running install scripts:

npm pack <package-name>
tar -xzf <package-name>-<version>.tgz
cd package

Read package.json first and check its scripts section, since a malicious npm postinstall script remains a top attack pattern. The dangerous hooks are:

  • preinstall
  • install
  • postinstall
  • prepare

Any of these running a shell command, downloading a file, or executing an obfuscated blob is an immediate stop sign. Legitimate packages sometimes use prepare to build from source, so context matters — but a tiny utility needing a network call at install time fails the smell test. Also compare the tarball contents with the description, looking for precompiled binaries (.node files) or bundled .env files. The imgdecode case proves why: its danger was a shipped binary that ran only when the package was loaded.

Step 3: Read the Shipped Code for Malware Signals

You do not have to read every line. Targeted searches catch most malicious packages:

grep -R -n "eval\|new Function\|child_process\|exec(\|spawn(" .
grep -R -n "process.env\|\.npmrc\|\.ssh\|\.aws" .
grep -R -n "fromCharCode\|Buffer.from.*base64" .

Investigate hits in these categories:

  • Dynamic code execution: eval or new Function on data from outside the package.
  • Process execution: child_process, exec, or spawn, especially with network calls.
  • Credential access: reads of process.env, .npmrc, .ssh, or .aws files. A formatting helper has no business reading your SSH keys.
  • Outbound calls and obfuscation: http/fetch requests to hardcoded domains, long base64 strings, fromCharCode chains, or .node files with no build script to explain them.

One pattern alone is not always proof — bundlers produce minified code legitimately. But several together, in a package that does not need them, is a strong reason to walk away.

Step 4: Check the Dependency Tree, Not Just the Package

A clean-looking package can drag in something dangerous. Check what else comes with it:

npm view <package-name> dependencies
npm install <package-name> --dry-run

A tiny helper pulling in 40 transitive dependencies is a red flag. Every extra dependency is another maintainer and another chance for compromise. Prefer small, well-maintained trees, and inspect the direct dependencies of anything you doubt — malicious code often hides one level down. A package-lock.json pins exact versions, so commit your lockfile and treat unexpected lockfile changes like code changes.

Step 5: Scan with Socket and Snyk — and Know What npm audit Misses

A Socket Snyk npm scan workflow covers more ground than npm audit alone — zero vulnerabilities there does not mean a package is safe:

  • npm audit: checks dependencies against known vulnerabilities. It finds known CVEs but cannot flag a brand-new malicious package with no CVE yet. Use it as a baseline, not a verdict.
  • Socket.dev: analyzes package behavior, including install-time code execution, flagging malware-like packages before any CVE exists.
  • Snyk test: scans for known vulnerabilities and monitors for newly disclosed malicious packages after you install.

Run at least one behavioral scanner on any package you do not already trust. Scanners can miss novel techniques, as the precompiled-binary trick shows, but they catch a large share of real-world malicious packages.

Step 6: Harden Your Install So One Bad Package Cannot Hurt You

Hardening limits the damage:

  • Use --ignore-scripts for untrusted packages — but understand npm ignore-scripts limitations. The flag stops preinstall, install, and postinstall scripts, blocking the classic attack. It does NOT stop precompiled add-ons: as imgdecode showed, a .node binary runs when the package is imported, not installed, so --ignore-scripts offers zero protection there. Use it, but never as a complete shield.
  • Pin versions, use lockfiles, and add a cooldown. Avoid floating ranges for critical dependencies. Tools like pnpm and Yarn support a minimum release age (for example, 3 days), so new versions wait for community scrutiny.
  • Install suspicious packages in isolation. Test unknown packages in a disposable Docker container, not on your main workstation. Never install as root in CI, where elevated privileges turn a malicious script into a full compromise.
  • Keep publishing credentials tight. npm revoked classic tokens on December 9, 2025; new write-enabled granular tokens enforce two-factor authentication by default and are capped at 90 days. Use granular tokens or trusted publishing.

Comparison: What Each Check Catches — and What It Misses

Check methodWhat it catchesWhat it misses
npm view metadataNew maintainers, typosquattingCode in trusted-looking packages
npm pack + scriptsMalicious npm postinstall scriptsBinaries that run on import
Code grepObfuscation, credential theftWell-hidden payloads
Dependency tree reviewRisky transitive dependenciesDependencies you trust
npm auditKnown vulnerabilities (CVEs)New malicious packages, no CVE
Socket.dev / SnykBehavioral flagsNovel scanner-blind techniques
--ignore-scriptsInstall-time script attacks.node binaries on require
Lockfiles + pinningSilent upgrades to compromised versionsA malicious version you pin

FAQ: Checking npm Packages for Malware

How do I check an npm package for malware in under five minutes?

Run npm view for metadata, then npm pack, read package.json scripts, grep for eval and credential reads, and run a Socket.dev or Snyk scan.

Does npm audit detect malicious packages?

Not reliably. It checks known vulnerabilities, not malicious intent, so a new malicious package with no CVE reports as clean. Pair it with Socket.dev.

Is --ignore-scripts enough to stay safe?

No. It blocks install-time scripts but not precompiled add-ons that execute on import, as imgdecode demonstrated. Combine it with code inspection and isolated testing.

Conclusion: How to Check an npm Package for Malware, Every Time

Knowing how to check npm package for malware comes down to one discipline: never install blind. Check the metadata, unpack with npm pack, read the install scripts, grep for credential theft and outbound calls, review the dependency tree, scan with Socket or Snyk, and harden the install with --ignore-scripts, lockfiles, and isolated testing. No single check is 100% reliable — imgdecode proved even standard advice has gaps — but layered checks catch nearly everything attackers actually ship.

For help auditing dependencies, see our services or contact us. Related reading: How to Check If Your WordPress Site Is Hacked and Cybersecurity 2025.

Sources: SafeDep, The Hacker News, GitHub Changelog

Leave a Comment