I think it has become abundantly clear that Node.js and how it deals with dependencies is flawed and has become a total liability now.
On October 22, 2021, a popular Npm package was hijacked and exposed to anyone who downloaded it to a password harvester and cryptocurrency miner for 4 hours. This package is called UA-Parser.js.
There is a good chance you might not have even heard of this. However, this package is downloaded almost 8 million times per week. Allegedly some large companies like Amazon, Facebook and Google are using this package.
Thanks to the work of the community and numerous partners, the issue was resolved in four hours. In a GitHub advisory, they detailed multiple versions of the rogue package that were created.
It would seem that these kinds of malware attacks are becoming increasingly common. Sonatype identified some rogue packages in their research, and Npm subsequently removed them within hours. In other research by Sonatype, they also revealed software supply chain attacks are up 650%.
It sounds confusing if you’re not familiar with the broken way in which Npm deals with dependencies. The issue with Node.js is that when you install a dependency, you’re not only installing that dependency but possibly hundreds of other dependencies that dependency requires. You might recall the Left Pad incident (not an attack) where the author just shut the dependency down, and it broke a heap of apps and packages.
In this article, the author details how Node.js can be attacked with minimal effort. In research from 2019, it turns out you would only need to hack 20 accounts to control half of the Npm ecosystem. It’s chilling, it’s sickening, and people should be angrier about this than they are. How did we become so dependent on a fragile ecosystem prone to malware and other types of attacks?
The solution already exists, and it’s staring at you right in the face (it’s in the title, after all).
Deno
In quite a famous talk in tech circles, Ryan Dahl introduced the world to Deno in a talk titled, “10 things I regret about Node.js.”
I am ignoring the obvious points about package.json
and how comically large the node_modules
directory can get, Ryan talks about the security of Node.js. The fact that it is not sandboxed by nature is one such problem. Although, I feel developers haven’t adequately considered this downside of Node.js.
I want to point out that I am only currently exploring Deno for my projects. I still primarily use Node.js because the front-end ecosystem has become highly dependent on it. Bundlers like Webpack rely on Node.js to function, and by extension, Node packages.
I would love to see the front-end ecosystem embrace Deno, but to my knowledge, nobody has even tried to do that yet. Node.js has become the Java of the front-end world. It’s just expected that it’s there.
The lack of sandboxing and security features is why these rogue Npm package attacks are so effective. They have full access to everything. The entire environment is up for grabs. It sounds insane saying it out loud, but Node.js provides so much power out of the box and doesn’t stand in your way.
Another thing Deno does is remove the need for a centralised package repository like Npm. It allows you to import packages from URLs. A simple Javascript import to a TypeScript or Javascript file will suffice. It then gets cached in the project directory, and it’s encouraged you check that cache into your Git repository.
Deno has yet to fully take off, despite releasing a stable 1.0 release in May 2020, because developers in the Node ecosystem are too heavily invested in Node.js. We also have a chicken and egg problem. A lot of the packages in the Node.js world are not available for Deno (yet). I bet developers would flock to Deno if it supported Npm’s insecure package management.
While Deno might not be entirely on par with Node.js in every facet of performance, it’s more than good enough to start using. We have a real problem in the ecosystem. Node.js cannot be trusted. That’s just an honest fact. It has become a liability.
I am also not saying that Deno is bulletproof and doesn’t have security holes that hackers could exploit of its own. The issue with Node.js isn’t Node itself; it’s the Node Package Manager. A centralised point of attack that has widespread influence and control over the Node ecosystem.
Imagine if there was only one bank for the entire world? Instead of your credit unions and larger banks, it was one centralised bank that held everyone’s money. That sounds like a bad idea. But it is precisely what Npm is. It’s a centralised bank for Node packages.
While the attacks haven’t resulted in catastrophic consequences just yet, I do believe it is only a matter of time before we see an Npm attack that causes some severe fallout. It just seems far too easy to compromise the account of a maintainer and then take control of their packages.
Can you imagine if the attackers found a way to infiltrate the systems of big tech companies through the UA-Parser attack? Imagine if Google or Facebook had their systems penetrated on a deep level, even if only for four hours, that’s enough time to cause some damage.
Or, here is another scenario to think about. What if a hacker infiltrates the Npm organisation itself?
On paper, they look like a highly qualified candidate. In the shadows, they’re working for a hacker group or government entity with the intent to attack the ecosystem from the inside out. It might sound far fetched, but if you wanted to compromise a large part of the web ecosystem, is it that far fetched?
Is it any wonder there is so much buzz around Web 3.0 and decentralisation? Time and time again, we keep being reminded why centralisation is terrible and dangerous.