JavaScript has had an interesting progression over the years. Going from a quick project finalized in days, to something used for styling the web, to full-blown frameworks that evolved at the same pace with browser capabilities, to its current state.
I cannot really describe the current state, because it’s somewhere between a relatively young programming language finally starting to mature and something it’s not: a server-side language. Not only that, it’s also trying to be a native language, an IoT language (a bit idealistically). It tries to do everything. And of course the language itself is not sentient, but the stubbornness of people who learn it and want to apply it everywhere is.
Going forward, I still haven’t fully explored the native or LLM capabilities yet, and although I have my doubts, what I want to iterate is that JavaScript belongs to the browser. And if the browser engine is installed server-side, then it’s a matter of choice that I’d rather not agree with.
Going further than just ideologically saying “it’s not meant for this,” I will focus on the fact that as long as we have these supply chain attacks, and we will have them, it shows that maturity is yet again distant from what I expected from the language so far.
The last time I argued against server-side JavaScript was in 2022, even though I had spent a decade writing JavaScript before that and always wanted to use it on the backend. I then presented several additional points, which essentially all boiled down to the necessity of establishing a complete server-side JavaScript ecosystem. That means monitoring, fallback scenarios, segmentation, and for startups it’s not a big issue since you mainly start from scratch. However for other cases, it did not make sense economically to diverge from an already established ecosystem (Java, C#, Python, etc).
“It’s always about security”
And at that time as well, my main concern was regarding security. Certainly attacks that happened back then were probably smaller in scope, but they were frequent and started to raise red flags. On our project we already had a custom repository where we installed and updated npm packages manually. Those packages added in the private repository were just being scanned by various security software that we already know by now lags behind the actual implementation of malware. Because exploits happen with clean code as well, not with the convoluted mess we imagine ‘the malicious’ code looks like.
Hacking and exploiting software is mainly about scanning, finding patterns (usually passwords), making use of the existing privileges, and escalating them if possible. This is something that no security scanner can catch beforehand because it’s inherently what everything is about software: code that uses a certain amount of privilege to do something.
And regarding putting JavaScript on the server and inherently the npm ecosystem, no matter how hardened it seems, the security entry points raise exponentially compared to keeping them on the frontend.
As alarm-raising as it seems with recent news of npm package hijacks or supply chain attacks, we need to understand that as long as JavaScript is limited to the client, the entry point is just the developer working on the package or installing it, or the client accessing the vulnerable app. That is not something that should be ignored, but it’s usually a 1:1 infection ratio. However, if we discuss about an npm ecosystem installed and running on the server, the entry points become everyone (every client connecting to that server). Instead of a 1:1 ratio, you end up with ∞:1 (not literally infinite, but let’s just say a many:1).
This is how malware is spread, only one developer getting hacked, a self-publishing software, self-replicating, going outward. And when there are many affected at once, we can almost experience a pandemic level of infections and the entire npm ecosystem is at risk by: super spreaders, someone with enough credentials to publish in multiple repositories, and little to no security guards.
Conclusion
A single compromised maintainer account can poison thousands of projects downstream. The npm ecosystem with its deep dependency trees and automatic updates, has become some of the worst things about javascript itself. That is why when infection happens the server side, you’re compromising the infrastructure can potentially serves millions of users.
I rest my case about JS. Until we figure out better isolation, better security scanning that actually works, and better privilege management in the npm ecosystem, better and more strict publishing process, javascript should stay where it was meant to be: in the browser.
Photo by Mohammad Rahmani on Unsplash.