How to Evaluate an npm Package: A Practical Checklist
Guide · June 8, 2026

How to Evaluate an npm Package:
A Practical Checklist

Every npm install is a trust decision. Here's how to make it an informed one — from package metadata to provenance attestation, install scripts, and audit tools.

TL;DR: Don't trust npm packages blindly. Check publish date, install scripts (npm view), weekly downloads, bundle size (npm pack --dry-run), GitHub health indicators, and run npm audit. Use npm install --allow-scripts=pkg1,pkg2 with npm 11.16+ to keep install scripts opt-in. The Mini Shai-Hulud attack (May 2026) is the latest reminder of what can go wrong — see my analysis of the Shai-Hulud npm supply chain attack for the full story.

Why Vetting npm Packages Matters

Every time you run npm install , you're granting that package's code — and every transitive dependency it brings along — full access to run on your machine, your build server, and potentially your production environment. The npm ecosystem is built on trust, and trust is exactly what attackers exploit.

The Mini Shai-Hulud supply chain attack in May 2026 compromised over 170 packages including TanStack, Mistral AI, and UiPath. Attackers gained access through maintainer account takeovers and used postinstall scripts to exfiltrate credentials and inject malicious code into production builds. This wasn't a theoretical attack — it affected real companies with real security teams.

More recently, the Red Hat Shai-Hulud backdooring incident in npm packages served as yet another wake-up call. Both incidents shared a common pattern: attackers targeted packages with high download counts but low maintainer oversight, used install scripts as the delivery mechanism, and relied on the fact that most developers never look at what actually runs during npm install.

The good news? npm 11.16.0 introduced --allow-scripts flags making install scripts opt-in by default. The ecosystem is moving toward better security defaults, but no CLI switch replaces developer judgment. This guide walks through every signal you should evaluate before adding a dependency to your project.

Beyond GitHub Stars: What Actually Matters

A package with 50,000 GitHub stars can be abandoned for three years. Stars measure popularity, not quality or safety. Here are the metrics that actually correlate with a well-maintained package.

Last Publish Date

The single most important signal. Check when the package was last published to npm:

npm view <package> time --json | tail -5

For actively maintained packages, expect a publish within the last 6 months. Packages untouched for 2+ years are red flags — they contain known CVEs, don't support modern Node.js versions, and won't get security patches when new vulnerabilities emerge.

Weekly Downloads and Dependents

Weekly downloads indicate community adoption. A package with 100,000+ weekly downloads has been battle-tested across thousands of projects. That said, download counts can be inflated by CI/CD systems that reinstall on every pipeline run. Cross-reference with dependents count:

npm view <package> dependents
npm view <package> description version downloads

Higher dependents means other package authors trust the API enough to build on top of it — a stronger signal than raw download count alone.

Bundle Size

A surprisingly large package may do more than you need — or include unnecessary dependencies. Check unpacked size and file count:

npm view <package> --json | grep -E "dist|unpackedSize"

For a visual comparison, use npm pack <package> --dry-run to see every file that will be installed. If a simple utility package ships 50+ files, ask why.

Pro tip: Use bundlephobia.com to check minified + gzip sizes before installing. A package that looks small in node_modules may have a heavy impact on your JavaScript bundle if it's loaded on the client side.

Install Scripts as Red Flags

npm lifecycle scripts (preinstall, postinstall, preuninstall) are shell scripts that run with your user permissions during npm install. They can read environment variables, access the filesystem, make network requests, and install additional software. They are the #1 attack vector in supply chain attacks.

How to Inspect Install Scripts

# Check if a package has lifecycle scripts
npm view <package> scripts

# See all files before installing
npm pack <package> --dry-run

If the scripts field contains postinstall without a clear node build.js or JS-based purpose, investigate further. Native modules (node-gyp rebuild) are legitimate reasons for postinstall scripts — but any script that downloads external resources or accesses the network is suspect and should be verified.

npm 11.16.0: --allow-scripts

npm 11.16.0 introduced a major security improvement: the --allow-scripts flag makes install scripts opt-in by default. Instead of all postinstall scripts running automatically, only explicitly approved packages can run them:

# Install with opt-in scripts (npm 11.16+)
npm install <package> --allow-scripts=<package>

This single change blocks the most common supply chain attack vector — a compromised package that quietly adds a malicious postinstall script. For a deeper dive into how this RFC evolved and what alternatives exist for package authors who previously relied on postinstall, see my analysis of the npm install scripts opt-in RFC.

Provenance Attestation: Cryptographic Supply Chain Verification

Provenance attestation is npm's answer to the question "was this package actually published by its maintainer from the real source code?" It uses Sigstore transparency logs and SLSA Build Level 2+ to cryptographically link a published package to a specific CI build job.

When a package has provenance, you can verify it was built on GitHub Actions (or another supported CI) from a specific repository commit:

# Check provenance for a package
npm view <package> --json | jq '.dist.attestations'

# Verify provenance at install time
npm install <package> --verify-provenance

Not every package publishes provenance yet — it requires explicit CI configuration and GitHub's OIDC token. But major frameworks and tooling are adopting it. When available, preferred provenance over non-provenance packages, especially for critical infrastructure like build tools, bundlers, and security libraries.

GitHub Health Indicators

A package's GitHub repository tells you more than its npm page ever will. Here's what to inspect before trusting a package with your production environment.

Commit Recency and Frequency

A healthy project has commits within the last 3-6 months. Check the pulse of the repository: are commits regular, or do they come in bursts around release time? Burst commits followed by long silences suggest dependency-driven updates rather than active maintenance.

Issue and PR Resolution

Go to the GitHub Issues tab and sort by "Most commented" or use GitHub's recently-updated filter. A project with 200 open issues and no responses from maintainers is a dead project. Healthy projects have a managing issue response time under 7 days and actively prune stale issues.

CI Badges and Test Coverage

A README without CI badges is a red flag. Look for GitHub Actions, CircleCI, or similar build status badges. Also check for code coverage, linting, and security scanning in the CI pipeline. A project that doesn't run tests before merging pull requests will inevitably ship bugs.

Maintainer Count

Bus factor matters. A project with a single maintainer who hasn't touched the repo in 8 months is a single point of failure. Projects with multiple maintainers (3+) from different organizations have better bus factor and typically more responsive issue triage.

Audit Tools: Defense in Depth

No single tool catches everything. The best dependency safety strategy combines several scanning approaches.

Tool What It Checks Strengths When to Use
npm audit Known CVEs against npm advisory database Built-in, zero setup, Snyk-backed advisory data Every install, every CI run
Socket.dev Security + quality signals (install scripts, typosquatting, network access, suspicious patterns) Detects supply chain risks that don't have CVEs yet, PR bot for new dependencies PR review gate, new package evaluation
Snyk Known vulnerabilities with fix guidance Broad database, integration with container scanning, license compliance CI pipeline, monthly deep audit
OpenSSF Scorecard Open-source project security practices (CI tests, SAST, token permissions, maintenance) Google-backed, checks security posture of the package's development process itself Pre-dependency decision for new packages
npm query Dependency tree structure and composition SQL-like queries on your node_modules, finds packages with install scripts, deprecated packages, duplicates Dependency tree audit, post-install inspection

Integrating into Your Workflow

# CI pipeline check (fail on critical)
npm audit --audit-level=critical

# Socket.dev CLI scan
npx socket scan

# Find all packages with install scripts
npm query ".scripts:not(.scripts == {})"

# Find all deprecated packages
npm query ".deprecated"

The npm query command is especially useful — it uses CSS-like selectors to search your dependency tree. You can find packages with specific properties, versions, or from specific authors:

# Packages with postinstall scripts
npm query ":attr(.scripts, [postinstall])"

Deprecation Signals: When to Replace a Package

Packages don't stay healthy forever. Watch for these deprecation signals in your existing dependencies:

When you identify a deprecating package, plan a migration. Don't wait for a critical CVE to force your hand. The best time to replace an unmaintained package is while you have time to evaluate alternatives properly.

Dependency Tree Analysis

A single direct dependency often pulls in dozens of transitive dependencies. That utility library you added for one function? It might bring 50 packages along for the ride.

Visualizing Your Dependency Tree

# Show the full tree
npm ls --all

# Show only production dependencies
npm ls --all --prod

# Show why a specific package is included
npm ls <package-name>

For large projects, npm ls --all can be overwhelming. Use npm ls <package> to trace exactly why a particular dependency ended up in your project — which direct dependency pulled it in.

Bundled vs Development Dependencies

Always check whether you actually need a development dependency in production. Tools like webpack, typescript, and eslint should be in devDependencies only. Putting them in dependencies bloats your production node_modules and increases attack surface.

# Count packages in each category
npm ls --prod | wc -l
npm ls --dev | wc -l

If your production dependency count is more than 10x your direct dependencies, your dependency tree has unnecessary depth — consider tools like npm dedupe or a monorepo with shared packages.

Practical Daily Checklist

Before adding any new npm package to your project, run through this checklist. It takes 2-3 minutes per package and has saved me from adding abandoned, bloated, or suspicious packages more times than I can count.

Before npm install

For packages the entire team will rely on (frameworks, bundlers, state management, security libraries), spend an additional 10 minutes: read the README thoroughly, check issue response times, review the last 10 commits, and check if the package has been audited by a third party.

License and Legal Considerations

License compatibility matters more than most developers realize. Your project's license must be compatible with every dependency's license. The most common conflict is GPL-licensed packages in proprietary software — GPL's copyleft provisions can force you to open-source your entire application.

# Check a package's license
npm view <package> license

# Get license list for all packages
npm licenses

# Or with npm-license-audit-cli for JSON output
npx license-checker --json

Safe defaults for commercial projects: MIT, Apache-2.0, BSD-2-Clause, BSD-3-Clause, ISC, Unlicense. Use these licenses as your acceptance criteria unless you have a legal team reviewing every dependency.

What Good Looks Like: A Reference Example

Let's look at a practical example. Say you're evaluating zod for schema validation. Here's what the signals tell us:

This is what a trustworthy package looks like across every dimension. When a package fails two or more of these checks, it's worth asking if you really need it, or if a simpler alternative exists.

FAQ

What should I check before installing an npm package?
At minimum: check the last publish date (should be within 6 months for active packages), weekly downloads (1,000+ for community-validated packages), package size, install scripts, license, GitHub stars vs issues ratio, and run npm audit on your project after install.
Are npm install scripts dangerous?
Yes. Install scripts (postinstall, preinstall, preuninstall) run arbitrary code on your machine with your user permissions. This is exactly how the Mini Shai-Hulud supply chain attack compromised 170+ packages in May 2026 — attackers used postinstall scripts to exfiltrate credentials and inject malicious code in production builds. npm 11.16.0 introduced --allow-scripts to make install scripts opt-in. For a detailed analysis of the attack, see my Shai-Hulud attack breakdown.
How do I check if an npm package has install scripts?
Run npm view <package> scripts to see lifecycle scripts. You can also inspect contents with npm pack <package> --dry-run which lists all files without downloading. For script content, extract and read the package's package.json or use npm query ".scripts:not(.scripts == {})" after installation.
What is npm provenance attestation?
Provenance attestation allows npm packages to include verifiable signatures proving they were built on a specific CI system (e.g., GitHub Actions). It uses Sigstore/Rekor transparency logs and SLSA Build Level 2+ to cryptographically link a published package to its source repository and build process. This means you can verify the package on npm is exactly what was built from the source code — no tampering in transit or at the registry.
Is GitHub stars a reliable metric for npm packages?
No. GitHub stars are vanity metrics — they can be bought, gamed, or accumulated over years without active maintenance. A package with 50,000 stars could be abandoned for 3 years. More reliable signals: weekly npm downloads, recent commit dates, open vs closed issue ratios, CI badge status, and maintainer responsiveness to pull requests and bug reports.
What tools should I use to audit npm dependencies?
Key tools: npm audit (built-in, CVE scanning), Socket.dev (supply chain risk detection, install scripts, typosquatting), Snyk (broad vulnerability database with fix guidance), OpenSSF Scorecard (project security practices evaluation), and npm query (dependency tree analysis). Use them together — no single tool catches every risk. Run basic checks (npm audit) on every CI run and deeper scans (Socket.dev, Scorecard) when evaluating new critical dependencies.
How often should I audit my dependencies?
Run npm audit on every install and as part of your CI pipeline (fail on critical vulnerabilities). Do a full dependency review at least monthly — check for deprecated packages, new CVEs, abandoned transitive dependencies, and dependency tree bloat. Major version bumps and framework upgrades are natural triggers for a comprehensive dependency review. The npm install scripts opt-in RFC is a good example of how the ecosystem is evolving to reduce audit burden — see my analysis of the RFC.

Need a Secure Web Application Built?

Evaluating npm packages is just one piece of building secure, maintainable web applications. Every project I build follows a structured approach to dependency management, security audits, and long-term maintenance planning. If you're planning a new project or want to improve an existing codebase, reach out to me for a free consultation.

I'm a full-stack developer with over 20 years of experience building production applications in React, Vue, Node.js, and beyond. Based in Minsk and working worldwide — let's discuss your project.

Contact

Let's discuss your project

Tell me about your project — I'll evaluate your tech stack and provide a preliminary estimate. Free of charge.