Installing a package from npm is an act of faith. You type a name, hit enter, and trust that the bytes flowing onto your machine are exactly what you expected and nothing more. Most of the time that faith is well placed. But npm is the largest software registry on the planet, which also makes it the largest attack surface, and a single typo or a hijacked maintainer account can turn a routine install into a security incident.
npq is a small command-line tool that inserts a deliberate pause into that moment. It audits npm packages before they are installed, runs a battery of heuristic and security-database checks, surfaces anything suspicious, and only then hands off to your real package manager to do the actual work. It does not replace npm, yarn, or pnpm; it sits in front of them as a pre-install safety gate. Maintained by Liran Tal, a well-known Node.js supply-chain security advocate, npq is open source under Apache-2.0, depends on only four runtime packages, and ships with no account, no SaaS, and no telemetry.
The core idea is to shift the check left. Traditional tooling like npm audit runs after you have already installed a package, by which point its install scripts may have already executed. npq inspects before the code ever touches disk, which is precisely the moment that matters for malware.
Why Pre-Install Matters
The threats npq is built to catch are the ones that bite hardest in real-world supply-chain attacks:
- Typosquatting — packages named just like popular ones (
loadsh,expres) hoping you fat-finger an install. - Malicious packages — published specifically to exfiltrate environment variables, steal tokens, or drop miners.
- Hijacked maintainers — a trusted package suddenly publishing a malicious version after an account takeover, as seen in the
event-streamandua-parser-jsincidents. - Brand-new throwaway packages — freshly published, no README, no repository, no license: classic markers of disposable malware.
- Dangerous install scripts — pre and post-install lifecycle hooks that run arbitrary code at install time, the single most common malware delivery mechanism.
- Expired maintainer domains — if a maintainer's email domain lapses, an attacker can re-register it, recover the npm account, and ship a poisoned update.
A quick word of honesty that npq's own documentation insists on: there is no guaranteed absolute safety. A malicious package with no publicly disclosed advisory could still slip through. npq raises the bar significantly; it does not eliminate risk.
The Marshalls
npq's checks are implemented as modular marshalls. Each one inspects a single dimension of the package and emits either a warning (non-fatal) or an error (fatal). The current lineup covers a wide spread of signals:
- age warns when a package is less than roughly 22 days old, and version-maturity warns when the specific version is under about 7 days old.
- author validates the publisher and flags newly added maintainers or sudden activity after a long dormancy, a classic takeover signal.
- downloads warns on very low adoption, and readme, repo, and license warn when those basic markers of a legitimate project are missing.
- scripts warns about pre/post-install lifecycle scripts, while newBin flags packages introducing new CLI binaries.
- typosquatting detects names suspiciously close to popular packages, and deprecation warns when a package is deprecated or its GitHub repo is archived.
- snyk queries the Snyk vulnerability database for known issues, and signatures plus provenance verify package signatures and sigstore-based attestations.
- maintainers expired emails flags publishers whose email domains have expired.
After the marshalls run, npq prints the findings and, assuming nothing fatal turned up, proceeds to install through the underlying package manager.
Getting It Onto Your Machine
The recommended path is a global npm install, because it also sets up the alias-based workflow described below:
npm install -g npq
Homebrew users have an equally simple option:
brew install npq
One requirement to note: npq needs Node.js >= 20.13.0, so it will not run on older runtimes. Installing it ships two binaries, npq and npq-hero, the second of which powers the drop-in npm replacement.
Your First Audited Install
The most explicit way to use npq is to call it directly in place of your package manager. It audits the package, prints what it found, and then forwards to npm:
npq install express
If you want to see the audit without actually installing anything, add --dry-run. This is perfect for kicking the tires on a package you are merely considering:
npq install express --dry-run
And if you would rather not install npq globally at all, npx works for a one-off check:
npx npq install express --dry-run
Each of these runs the full marshall suite. When only warnings appear, npq pauses briefly and then continues; when a fatal error is detected, it stops before anything is installed.
Becoming Your Default npm
The headline pattern, and the reason npq is so easy to adopt, is aliasing the npm command itself to the npq-hero binary. Once you do this, every single npm install you run is transparently audited first, with zero change to your muscle memory or your scripts:
alias npm='npq-hero'
Now a familiar command like npm install lodash quietly runs the npq checks and then forwards the complete command to the real npm. Because npq-hero passes arguments straight through, your existing workflows, CI scripts, and habits all keep working exactly as before, only now with a security pre-flight bolted on.
If you live in yarn or pnpm, npq can drive those too by way of the NPQ_PKG_MGR environment variable:
alias yarn="NPQ_PKG_MGR=yarn npq-hero"
NPQ_PKG_MGR=pnpm npx npq install fastify
This composability is a big part of npq's appeal: one tool fronts whichever package manager your team has standardized on.
Turning Warnings Into a Hard Gate
Here is the most important behavior to understand, and the one that trips people up. By default, when npq finds only warnings and no fatal errors, it waits about 15 seconds and then auto-continues with the install. This keeps the tool non-blocking for everyday use, but it also means warnings alone will not stop you unless you tell npq to be stricter.
To turn npq into a genuine gate that refuses to proceed on warnings, disable auto-continue. You can do it per-command:
npq install express --disable-auto-continue
Or set it globally for an entire shell session or CI environment:
export NPQ_DISABLE_AUTO_CONTINUE=true
With auto-continue off, a flagged package halts the install and waits for a human decision rather than quietly proceeding. This distinction matters: the default mode is a friendly heads-up, while the gated mode is an actual barrier.
Tuning the Marshalls
Heuristics are noisy by nature. Legitimate internal or freshly scoped packages will trip the age, downloads, or readme marshalls, and you do not always want that noise. npq lets you selectively disable individual marshalls through MARSHALL_DISABLE_<NAME> environment variables:
MARSHALL_DISABLE_AGE=1 npq install express
MARSHALL_DISABLE_SNYK=1 npq install express
The full set you can toggle includes MARSHALL_DISABLE_AGE, _AUTHOR, _DOWNLOADS, _MAINTAINERS_EXPIRED_EMAILS, _LICENSE, _PROVENANCE, _REPO, _SCRIPTS, _SIGNATURES, _SNYK, _TYPOSQUATTING, _VERSION_MATURITY, _NEWBIN, and _DEPRECATION. This is how you tame false positives without giving up the checks that actually matter to you.
One marshall worth calling out specifically is snyk. To enable the known-vulnerability database lookup, you need to provide a Snyk API token:
export SNYK_TOKEN="your-token-here"
npq install express
Without that token you lose the CVE database check and fall back to the heuristic marshalls alone, which is still useful but covers different ground.
Wiring It Into CI
npq is at its most valuable when it runs automatically, and CI pipelines are a natural home. There are two main patterns. The first is a one-off audit step using npx, with --dry-run to inspect without installing and --plain for clean, machine-readable logs:
npx npq install some-new-dependency --dry-run --plain
The second pattern actually gates installs in the pipeline. Because you want warnings to block rather than silently proceed in an automated context, you disable auto-continue and lean on plain output:
NPQ_DISABLE_AUTO_CONTINUE=true npq install some-new-dependency --plain
For CI you will usually also want to set SNYK_TOKEN in the environment so that vulnerability data is folded into the audit. Together these flags turn npq into a dependency-introduction checkpoint that runs on every pull request that touches your manifest.
Where npq Fits Among the Alternatives
It helps to understand npq's lane relative to the other tools in this space. npm audit is reactive: it scans your installed dependency tree against the advisory database, but only after install scripts have already executed, and it only knows about disclosed CVEs, not typosquats or heuristic red flags. Socket offers heavier behavioral static analysis as a partly commercial SaaS with dashboards and a GitHub app, which is more powerful but also more setup and cost. The Snyk CLI focuses on vulnerability and license scanning with remediation advice, and npq actually borrows Snyk's database through its snyk marshall.
npq's sweet spot is being the lightweight, zero-account, open-source first line of defense you run locally before installing, and being trivially aliasable over npm so it runs without you thinking about it. It is worth being clear-eyed about a couple of its boundaries too: it audits the packages you explicitly install rather than walking the entire transitive dependency tree, and it is a gate on direct additions rather than a whole-graph scanner. It complements the post-install tooling rather than replacing it.
The Thirty-Second Safety Net
What makes npq compelling is the ratio of protection to effort. Add a single alias and every install you run from that day forward is quietly audited for typosquats, throwaway packages, dangerous install scripts, archived repositories, expired maintainer domains, and missing provenance, all the things that npm audit simply does not look for. It runs locally, ships no telemetry, leans on a tiny dependency footprint, and comes from a maintainer with deep credibility in the supply-chain security world.
It will not catch everything, and it does not pretend to. But the most expensive supply-chain compromises tend to come from exactly the kind of obvious-in-hindsight signals that npq is built to surface at the only moment they can still help: before the code runs. If you want a meaningful upgrade to your install hygiene without changing how you work, aliasing npm to npq-hero is about as good a return on thirty seconds of effort as you will find.