# Why Would You Ever Choose Node?

Author: Matthew van Bird (https://mattvanbird.co.uk/about)
Published: 2026-11-04
URL: https://mattvanbird.co.uk/article/why-would-you-choose-node

> Our Node services get hammered with vulnerabilities daily and .NET is fine. npm takes eleven advisories a day to NuGet’s one. Use Node when you must.

### Every day

At work our Node services are getting hammered with vulnerabilities, every day. Our .NET services are fine. Normal cadence.

This site has both, and Rust as well. It has three backends and I gave each one a different language on purpose, so I'd have a spread. The chatbot is .NET, the view counter is Rust and the website scanner behind `/demystify` is Node.

### Counting

The .NET chatbot references four packages, and they pull in one more. All five are Amazon's, for Lambda and for Bedrock. The JSON and the Telegram alerts come out of the standard library, so every line of code it runs comes from this repo, Microsoft or Amazon.

The Node scanner has five direct dependencies and 78 packages in its lockfile. Thirty-one of them are Amazon's, because the AWS SDK for JavaScript comes in pieces. In .NET the chatbot gets the same SDK in two packages. The other 47 have 32 different maintainers between them.

Fifteen of those are there because `puppeteer-core` depends on Google's tool for downloading browsers, and that tool has a command line. It installs `yargs` to read its arguments, and `yargs` brings a library that works out how wide a line of text will be in a terminal, along with a regular expression that matches every emoji. The scanner runs on Lambda, which has no terminal.

The Rust view counter compiles about 170 crates to read and write one DynamoDB table. Until I cut its features back, it was building two separate HTTPS stacks, because that's what the AWS SDK's defaults gave it.

So Rust lost the count. Cargo has the same shape as npm. It's a big registry of small packages, and their build scripts run on your machine when you compile. I'd still pick Rust over Node, because crates.io hasn't been hit the way npm has.

### The last year

In September 2025 someone phished the maintainer of `chalk` and `debug` with a fake npm support domain, then published poisoned versions of eighteen packages that between them get downloaded more than two billion times a week [1]. A week later a worm called Shai-Hulud started stealing credentials from the machines it was installed on and using the npm accounts it found to publish itself into more packages. CISA counted more than five hundred [2]. In November it came back running in `preinstall`, so it went off the moment `npm install` reached it, and within days it had dumped stolen secrets into more than 25,000 new GitHub repositories [3].

Each time the way in was somebody's npm account and a package people already trusted.

### This year

npm has had about eleven new advisories a day this year, and NuGet about one [4].

That's new. GitHub reviewed about 600 npm advisories in the whole of 2025, around fifty a month. Since March it's been between about 180 and 600 a month, and nine in ten carry a 2026 CVE number, so these are holes found this year rather than old ones filed late. By May the CVEs GitHub issues were up 476% on the year, and GitHub told VulnCheck the findings were real. VulnCheck says that fits people hunting bugs with AI, though it can't put all of it down to that [5].

This is the year so far, January to the start of November [4].

| 2026 so far | npm | NuGet |
|---|---:|---:|
| New advisories | 3,416 | 401 |
| A day | 11 | 1.3 |
| Critical | 387 | 17 |
| Malicious packages | 13,433 | 22 |

npm has about 4.6 million packages [6] and NuGet about 590,000 [7], so you'd expect npm to have about eight times the advisories, and it does. Per package, that's level. But one npm advisory in nine is critical, against one in twenty-four for NuGet, so an npm package is three times as likely to get a critical one. It's eighty times as likely to turn out to be malware.

Anthropic pointed its Claude Mythos Preview model at more than a thousand open source projects, and by June it had sent 1,596 vulnerability reports to the maintainers of 281 of them. By then the maintainers had patched ninety-seven [8].

Every fix waits on whoever maintains the code. For the .NET standard library that's Microsoft, which ships fixes on Patch Tuesday, the second Tuesday of the month [9]. That's our normal cadence at work. For the scanner it's Amazon and those 32 other maintainers, each one fixing things whenever they get to it.

### Install scripts

Shai-Hulud spread because npm ran a package's install scripts as soon as you installed it. npm 12 turned that off by default this summer [10], eighteen months after pnpm did [11]. Every LTS release of Node comes with npm 10 or 11, and those run them [12]. Unless you've upgraded npm yourself, `npm install` runs whatever install scripts it finds.

Go never had them. Fetching or building a Go module runs none of its code. Go isn't clean either. A typosquat of BoltDB with a backdoor in it sat in Google's module mirror for more than three years before Socket found it in early 2025, and the mirror kept serving the backdoored version after the attacker cleaned up the GitHub repo to hide it [13]. Attackers go after every registry. They go after npm the most, because it's the biggest, and because for most of its life installing a package ran its code.

### When Node is the answer

Use Node when the thing you need only exists there. A frontend build is the obvious one. This site's Vite build pulls 191 packages through npm, and there's no way round npm for that. Put everything else in .NET, Go or Rust. Not Java. Java is very 80s.

The usual reason for a Node backend is that the team already knows JavaScript. That's how a frontend team ends up owning an API because nobody wanted to learn a second language, and how the API inherits npm because the frontend already had it. I've [written about the npm side before](https://mattvanbird.co.uk/article/nuget-vs-npm-dependency-poison), and the hygiene in that piece applies when you can't avoid it. It's a lot of work to take on for a backend that didn't need to be Node.

### To finish

Node is a decent runtime bolted to a registry that takes eleven new advisories a day. Use it when nothing else will do, and the rest of the time pick something whose standard library does the work, so strangers aren't writing half your program.

### Sources

1. [Cycode, "npm debug / chalk supply-chain attack: The complete guide"](https://cycode.com/blog/npm-debug-chalk-supply-chain-attack-the-complete-guide/)
2. [CISA, "Widespread Supply Chain Compromise Impacting npm Ecosystem", 23 September 2025](https://www.cisa.gov/news-events/alerts/2025/09/23/widespread-supply-chain-compromise-impacting-npm-ecosystem)
3. [CSO Online, "New Shai-Hulud worm spreading through npm, GitHub"](https://www.csoonline.com/article/4095578/new-shai-hulud-worm-spreading-through-npm-github.html)
4. [OSV.dev data exports for npm and NuGet, GitHub-reviewed advisories and malicious package reports by publish date, counted 4 November 2026](https://google.github.io/osv.dev/data/)
5. [VulnCheck, "The First CVE Wave: Signs That AI-Assisted Vulnerability Discovery Is Reshaping Disclosure Volumes", 14 May 2026](https://www.vulncheck.com/blog/ai-assisted-vulnerability-discovery)
6. [npm registry replication endpoint, document count](https://replicate.npmjs.com/)
7. [NuGet Gallery statistics, unique packages](https://www.nuget.org/stats)
8. [eWeek, "Anthropic Mythos Finds 23,019 Vulnerability Candidates as Patching Lags", 16 June 2026](https://www.eweek.com/news/anthropic-mythos-patching-lags/)
9. [Microsoft, ".NET and .NET Core Support Policy"](https://dotnet.microsoft.com/en-us/platform/support/policy/dotnet-core)
10. [InfoQ, "npm 12 Released: Install Scripts off by Default as Registry Moves to Explicit Trust"](https://www.infoq.com/news/2026/08/npm-12-released/)
11. [pnpm v10.0.0 release notes](https://github.com/pnpm/pnpm/releases/tag/v10.0.0)
12. [Node.js release index, with the npm version each release ships](https://nodejs.org/dist/index.json)
13. [InfoWorld, "Malicious package found in the Go ecosystem"](https://www.infoworld.com/article/3817921/malicious-package-found-in-the-go-ecosystem.html)
