CLI tool
lirantal/npq avatar
lirantal/npq

npq: audit an npm package before it is installed

safely install npm packages by auditing them pre-install stage

1,795 stars44 forksJavaScriptApache-2.0

At a glance

What is it?
npq is a command line tool that stands in front of your package manager and checks a package before anything is written to disk, looking at published vulnerabilities, package age, download counts, missing README and licence files, and the presence of install scripts. It also ships an alias mode so that every npm install goes through the gate without you having to remember it.
Who is it for?
Adopt npq if you install packages from the npm registry often enough that the pre-install check costs you a few seconds and saves you from a package with a suspicious install script, and if your team will accept a wrapper in front of npm. Do not adopt it as a security control on its own, because the project states plainly that a malicious or vulnerable package could still pass the checks, and do not expect it to replace a lockfile review or a dependency audit tool.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 16 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A pre-step in front of the package manager

npq allows you to audit npm packages before you install them. The project description is more compact: safely install npm packages by auditing them pre-install stage.

The shape of the tool is that of a wrapper. You run npq instead of your package manager, it does its checks, and when it is satisfied it hands the actual install job over to the package manager, npm by default or whichever one you specify. Nothing is written to node_modules until the checks have passed.

The author is Liran Tal, who writes about malicious modules in the npm ecosystem, and the project sits squarely in the application security space rather than the developer convenience space. The repository topics make that explicit with appsec, security-audit, supply-chain-security, vulnerabilities and vulnerability-scanners among them.

It is published to npm as npq, the licence is Apache-2.0, and the primary language is JavaScript. The releases are frequent, with v3.27.0 on 2026-08-25, v3.27.1 and v3.27.2 both on 2026-10-07, and the last push to the repository on 2026-10-07.

The check itself is short, and the README gives the whole list of what npq looks at before it lets an install proceed.

Six signals, and one honest disclaimer

The sanity check performs six steps, and they are a mix of hard data and heuristics.

The first is the one that matters most: npq consults the snyk.io database of publicly disclosed vulnerabilities to check whether a security vulnerability exists for that package and its version. The second is the package age on npm, since a package published last week has had no time to accumulate reports. The third is the package download count as a popularity metric.

The remaining three are structural. It checks whether the package has a README file, whether it has a LICENSE file, and whether it has pre or post install scripts.

That last check is the one that will stop most installs, and it is the most consequential. An install script is arbitrary code that runs with your user's privileges at install time, before you have read a line of the package. A published package with a postinstall hook that reaches out to the network is exactly the shape that the malicious module write-ups describe, and flagging it before it runs is the point of the tool.

The README is explicit about what this does not buy you, and it is worth quoting rather than paraphrasing: there is no guaranteed absolute safety, and a malicious or vulnerable package could still exist that has no security vulnerabilities publicly disclosed and passes npq's checks.

That sentence is the honest framing of the whole project. npq raises the cost of a careless install and gives you a second look, but it is a heuristic gate, not a guarantee, and a package that has never been reported to a vulnerability database is not a package that has been cleared.

Auto-continue, and the fifteen seconds you should probably turn off

There is one behaviour in npq that is a product decision rather than a technical one, and it is documented at length.

By default npq uses an auto-continue mode when warnings are detected, as long as they are warnings and not errors, waiting 15 seconds before proceeding with the installation. The idea is that a warning you have read does not need a keypress, and fifteen seconds is enough to notice and abort.

The README recommends the other behaviour for anyone who cares about the guarantee. You can disable the auto-continue with the --disable-auto-continue CLI flag or with the NPQ_DISABLE_AUTO_CONTINUE=true environment variable, and the description of that mode is enforcing a strict review and security hardened installs. The details are in the auto-continue documentation under docs/feature.

The two modes are a genuine trade-off. Auto-continue keeps a fifteen second tax on every install, which most people will learn to stop noticing, which defeats the purpose. Strict mode makes every install require a deliberate action, which is exactly what you want in a security-sensitive pipeline and exactly what makes people uninstall the tool.

The environment variable form is the one to set in a CI configuration, where the interactive prompt is not an option at all, and the flag form is the one to set in your shell profile for interactive work. The distinction between warnings and errors also matters, because the auto-continue only applies to the former.

The dry run, and the two binaries

The quickest way to see what npq does is the one-liner in the README:

sh
npx npq install express --dry-run

The explanation of that command is precise. The npx tool downloads and executes the npq package, runs an install check for the express package, and the --dry-run flag means npq exits regardless of success or errors. So you get the report without the install, which is the right way to evaluate the tool on a package you are curious about.

There are two binaries in the package, and the distinction explains the rest of the design. The package manifest declares bin entries for npq, which is the interactive command you run directly, and npq-hero, which is the alias-friendly entry point.

The npq-hero name is the point. The README recommends installing with npm rather than yarn, because that way npq can automatically install shell aliases for you. The alias you want is:

bash
alias npm='npq-hero'

With that in place, every npm command you type is routed through the gate, and the check happens for installs without you having to remember to invoke anything. The README frames this as embedding npq in your day to day npm usage so that there is no need to remember to run npq explicitly.

There is a demo video linked from the README and a screenshot, plus a long list of media coverage, which for a security tool of this kind is mostly a sign that it is one of the more visible projects in the npm safety space, by an author who has been writing about the problem for years.

Offloading to yarn, pnpm or anything else

Since npq is a wrapper rather than an install implementation, it has to know which package manager should do the actual work, and that is the NPQ_PKG_MGR environment variable.

The documented forms cover the common setups. For yarn 1.x, the alias is alias yarn="NPQ_PKG_MGR=yarn npq-hero". For yarn 4.x, the environment variable is set on the command itself, either with yarn run npq-hero or with yarn exec npq-hero. For pnpm, there is a direct invocation, NPQ_PKG_MGR=pnpm npx npq install fastify, and an alias form:

bash
alias pnpm="NPQ_PKG_MGR=pnpm npq-hero"
pnpm --filter workspace... add express

The pnpm alias example is worth pausing on, because it shows a case that the yarn example does not. The command passes a filter, pnpm --filter workspace..., and that argument has to survive the handoff from the alias to npq to pnpm unchanged. It is the kind of detail that separates a wrapper that handles arguments properly from one that breaks on the first flag it does not recognise.

The README also states the general rule: npq by default offloads all commands and their arguments to npm, or to the other package manager as specified, after it has finished its due-diligence checks for the respective packages. So the wrapper is not limited to install, and any command that touches a package goes through the gate.

Registries, and the privacy guarantee

Private registries are handled properly, and the documentation for it is unusually thorough.

npq reads the standard npm registry configuration, including the default and scoped registries, authentication, proxies and TLS settings. That means an existing .npmrc is respected, including a corporate registry with its own credentials, and it means the checks run against the same registry the install will come from, which is the only way the audit is meaningful.

You can also select a registry on the command line, and the option is shared with the package manager used for the installation:

sh
npq install @company/tool --registry=https://artifactory.example.com/artifactory/api/npm/npm-virtual/

The custom registry documentation covers .npmrc examples, configuration precedence, private CA setup, skipped capability behaviour and what the README calls npq's no-fallback privacy guarantee.

That last item is the one to look at. A tool that checks a package against a public vulnerability database and then installs it from a private registry has two questions to answer: does the check query go to the public service with your package names in it, and does the install fall back to the public registry if the private one is unreachable. The no-fallback guarantee is the answer to the second question, and the private CA setup is about the first, since a corporate network with an inspection proxy will fail to verify a public service's certificate otherwise.

The dependencies behind this are visible in the package manifest: @npmcli/config for reading the npm configuration, npm-registry-fetch for the registry calls, npm-package-arg for parsing package specifiers such as a scoped name, and semver for version comparison against the vulnerable ranges.

The supply chain tooling in the dependencies

The dependency list of a security tool deserves a careful read, and this one is small and pointed.

There is sigstore, which is the infrastructure for signing and verifying artefacts with a keyless identity, and ssri, the standard for expressing integrity hashes of npm packages. Both are there so that npq can talk about integrity in the same vocabulary the registry does, rather than inventing one.

The rest are plumbing: @npmcli/config, npm-registry-fetch, npm-package-arg, semver, and cross-spawn to run the package manager process. There is no heavyweight framework, no database and no service dependency, which is what you want in a tool that sits between you and your package manager and has to be fast.

The build and release setup is equally considered. The lint script is not just ESLint, it also runs a lockfile lint that validates the lockfile uses HTTPS and is restricted to the allowed hosts npm and npm, which is a guard against a dependency pointing at an unexpected registry. The publish configuration enables provenance, so the published artefact is attested. Releases go through semantic-release, the version in the manifest is 0.0.0-development because the tool writes the real version at publish time, and husky installs the git hooks.

The engines field requires npm 11.10.0 or later and Node 24.0.0 or later, which is a modern floor and worth checking before you install it into an older CI image. The tests are Jest, the repository has a SECURITY.md with a responsible disclosure badge, and the packages are published with the files list restricted to bin/, data/, lib/, schema/ and scripts/.

Editorial conclusion

Adopt npq if you install packages from the npm registry often enough that the pre-install check costs you a few seconds and saves you from a package with a suspicious install script, and if your team will accept a wrapper in front of npm. Do not adopt it as a security control on its own, because the project states plainly that a malicious or vulnerable package could still pass the checks, and do not expect it to replace a lockfile review or a dependency audit tool. Before you start, decide whether you want the 15 second auto-continue or the strict mode with --disable-auto-continue, and if you use a private registry, read the custom registry documentation so the audit runs against the registry you actually install from.

Frequently asked questions

What does npq check before installing an npm package?

It consults the snyk.io database of publicly disclosed vulnerabilities for the package and version, and it looks at the package age on npm, the download count as a popularity metric, whether there is a README file, whether there is a LICENSE file, and whether the package has pre or post install scripts.

Does npq guarantee that a package is safe to install?

No. The README states there is no guaranteed absolute safety, and a malicious or vulnerable package could still exist that has no security vulnerabilities publicly disclosed and passes npq's checks. It is a heuristic gate, not a guarantee.

How do I make npq stop auto-continuing after a warning?

Use the --disable-auto-continue CLI flag or the NPQ_DISABLE_AUTO_CONTINUE=true environment variable. By default npq waits 15 seconds and then proceeds when it finds warnings rather than errors, and the strict mode is what the README describes as enforcing a strict review and security hardened installs.

How do I use npq with yarn or pnpm instead of npm?

Set the NPQ_PKG_MGR environment variable to the package manager, for example alias yarn="NPQ_PKG_MGR=yarn npq-hero" for yarn 1.x, or alias pnpm="NPQ_PKG_MGR=pnpm npq-hero" for pnpm. npq performs its checks and then offloads the command and its arguments to that package manager.

How do I try npq without installing anything?

Use npx npq install express --dry-run, which downloads and runs npq through npx, runs the install check for the package, and exits without installing because of the dry run flag.

Official sources

  1. Issues
  2. License: Apache-2.0
  3. lirantal/npq on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/lirantal-npq.svg)](https://hysenlabs.com/projects/lirantal-npq)

Was this useful?