Security
Middleware is not authorization
Four NestJS advisories in seven months, all one bug: the matcher and the handler disagreed about the request. The check belongs where the data is read.
On 11 May 2026, between 20:19 and 22:56 UTC, someone with a stolen npm publish token pushed eighteen versions of @beproduct/nestjs-auth — 0.1.2 through 0.1.19. They carried a payload from the Mini Shai-Hulud supply-chain worm. It is tracked as CVE-2026-46412, CVSS 10.0, and it has no patched version, because there is no fix for a package that was malicious on purpose. npm removed it.
The payload ran on install and went looking for credentials: npm tokens, GitHub personal access tokens, OAuth tokens, and the OIDC tokens that CI jobs use to authenticate to cloud providers. Then it used them to publish itself further. That is what makes it a worm rather than a theft — every developer who installed it became a publisher of it.
Nobody had to run the application. npm install was enough.
A lifecycle script — preinstall, install, postinstall — is code from a stranger, executed by your shell, as your user, with your environment. Your environment contains NPM_TOKEN, GITHUB_TOKEN, ~/.ssh, ~/.aws, a .env file, and on CI an OIDC token that can mint cloud credentials.
We accept this a hundred times a day because the alternative sounds impractical. It is not.
Install with scripts disabled. For most dependency trees this simply works:
npm ci --ignore-scriptsSome packages genuinely need a build step — native modules, mostly. Find them, list them, and allow those specifically rather than allowing everything. If you use pnpm, onlyBuiltDependencies expresses exactly this.
Never install from a floating range in CI. npm ci installs the lockfile. npm install may resolve a caret range to a version published nine minutes ago. The eighteen malicious versions above were all inside somebody's ^0.1.0.
Delay adoption. A cooldown — refusing to install any version published in the last few days — would have covered the entire window of this incident, and of most others like it. The bad versions were live for hours, not weeks.
Scope the tokens. A publish token that can push every package you own is a worse loss than one that can push one package. Prefer short-lived OIDC over long-lived secrets in CI, and keep publish tokens off developer laptops entirely.
CVE-2025-54782 in @nestjs/devtools-integration, patched in 0.2.1, is the same lesson from the other direction. The package ran a local HTTP server with an unsafe JavaScript sandbox and no cross-origin protection. Any website a developer visited while it was running could execute code on their machine.
A development server bound to localhost is not private. Every page in the browser can send requests to it. Treat dev tooling as something that must be off when you are not using it, and pin it out of production dependencies.
Assume every credential that existed in that environment is gone. Rotate them: npm tokens, GitHub tokens, SSH keys, cloud keys, anything in a .env on that machine. Then read your npm and GitHub audit logs for publishes and pushes you did not make — the theft is not the damage, the use of what was stolen is.
For a firm that deploys other people's projects, the exposure is not one laptop. It is every client whose deploy key sat on it.
You cannot read every dependency. Nobody does. What you can do is stop granting install-time code execution by default, stop resolving versions at build time, and hold credentials that expire. None of that requires trusting the ecosystem less than you already, quietly, should.
Security
Four NestJS advisories in seven months, all one bug: the matcher and the handler disagreed about the request. The check belongs where the data is read.
Security
One RCE at CVSS 10.0, then six denial-of-service patches in eight months. When the contract is "accept whatever the format encodes", fixing one lever leaves the rest.
Security
Sixteen advisories in one day across fourteen projects, and most of them say access bypass. The fix is not more diligence, it is a shorter module list.