Hacker News new | past | comments | ask | show | jobs | submit login
Ask HN: Why is Node.js more susceptible to supply chain attacks than e.g. PHP?
15 points by noduerme 62 days ago | hide | past | favorite | 15 comments
I guess npm package naming anarchy and dependency rot come to mind, and security weaknesses inherent in distributed FOSS development. But inherently there's nothing a bad js script can do to your server that a malicious php script couldn't have done twenty years ago if you used the wrong package. Why has supply poisoning become such a problem with the Nodejs ecosystem in particular?

Because Node packages are too fine-grained meaning the dependency trees and attack surface are greater - what in PHP would be a single library from a single vendor could be a thousand packages in Node.

Because PHP packages are vendored by default, so there's an implicit stopgap on the propagation of issues from upstream.

Because PHP isn't dependent on a single vendor with a single global namespace, which avoids several of the issues you mentioned.

You can basically repeat that for other languages whose ecosystems benefit from the wisdom of years accumulated around package management and library design that Node seems to ignore.

edit: and the more I think about it, I suspect a lot of the bad practices in the modern JS ecosystem are due to the paradigm of having the same language running in the browser and on the server. This creates conflicting incentives in the way things are designed and deployed and one necessarily undermines the other.

npm didn't historically do lock files either, thus is was easier to update npm packages unintentionally.

npm is also a worse designed cli, just executing npm without any arguments and it will start installing regardless of where you are in the filesystem.

"I suspect a lot of the bad practices in the modern JS ecosystem are due to the paradigm of having the same language running in the browser and on the server. This creates conflicting incentives in the way things are designed and deployed and one necessarily undermines the other."

What do you mean. Could you give some examples?

Sorry, I have a bad habit of posting when I'm halfway out the front door for something...

For instance, as I understand it, the reason Node packages are so small is to make it efficient to run them in browsers. But that also exponentially increases the brittleness and vulnerability of the code. Optimizing for the always-live continuous deployment processes of web development runs counter to what is necessary for stable and secure code on the backend.

I may be wrong, though, it's just something that occurred to me while I was wondering about this exact problem.

> as I understand it, the reason Node packages are so small is to make it efficient to run them in browsers

Usage of npm packages in browsers is kind of an after thought, as originally people used a separate dependency management for the browser (bower js)

The NPM ecosystem has a huge focus on reusability of libraries, smaller packages is just an emerging phenomenon when reusability is the goal.

Also, small packages are a way to embrace the Unix philosophy, "do one thing and do it well"

But yes, smaller packages create large dependency chains and a greater attack surface...

Interesting, thanks

I'm not sure it is. Software development has become more decentralized and more complex than it was 20 years ago. It's also much more accessible to more people who may be great programmers but not really aware of code/repository security.

Most software developers do not sign their git commits. And if they do, they probably aren't doing it properly (store keys on a YubiKey or only use QubesOS with an isolated dev qube and split GPG).

If you do any sort of dev work, you really need to isolate that activity from the other things you do online and generate a signing only GPG subkey and handle it properly and sign all of your git commits. I think this is vital to ensuring code integrity as if you do not do this, you probably won't even realize when someone has tampered with your code.

Hope this helps.

Most replies here are missing the forest for the trees. The oft not acknowledged reason is that the JS ecosystem has a developer experience that scales a lot better than other languages. Your Java/Python/Dart/Ruby (or C++ if you include tooling like dpkg and brew) dependency managers suffer from what's commonly referred to as "dependency hell", or what in certain specific cases is called the diamond dependencies problem. They fundamentally don't scale and you get package conflicts easily. The npm approach (which was later adopted by Rust and Go) allows for installation of dependencies with arbitrarily large dependency trees without having to worry about hacks like Java's dependency shading or namespace conflicts (most of the time at least). People may complain about JS dependency managers' upstream security problems, but from a classic CS point of view, it is inherently superior as it reduces the amortized complexity of a SAT solver to a much simpler backtracking resolver.

See feross's reply for a better explanation: https://news.ycombinator.com/item?id=30964442

Things like vendoring, upstream version metadata to reduce redundant network requests, SHA verification, are all easy to add after the fact. Support for arbitrary dependencies on the other hand often require a certain amount of support on the compiler level (to detect conflicting exported data structures) which is why many languages cannot easily switch to newer package management architectures.

Beside the technical aspects that others already mentioned, I think there is also a social aspect. PHP vs Node is like the old Apple ads "I'm a Mac vs I'm a PC" where Node is Mac, it is modern and the future, the person is dressed as slacker and taking it cool. PHP is PC, old school with a blazer and pens in his shirt pocket, your class mate who came to school with an attaché case. It is in-group vs out-group.

If you are going to target something, you pick what you think is going to get the most effect, thus you pick the in-group, not the out-group.

PHP is in-group in one area and that is Wordpress, and of course it also constantly targeted.

I'm skeptical of this. People used to say that Windows viruses were much more common than Mac viruses because there were so many more PC users, the market share just made Windows a more attractive target. If this[1] is to be believed, in spite of its outsized footprint in recent supply chain hacks, Nodejs is still really only backing 1/20th the number of sites as PHP, and 1/7th as many as ASP.


yeah but those PHP websites are mostly legacy stuff that would completely break if automatically updated to the latest version of any package

whereas node.js is clearly dominant for new websites, and we all use hundreds/thousands of new packages every month without even giving it a second thought

Is it clearly dominant? I work with both, and for original/personal stuff I'd rather work in Nodejs as a coder (especially if I'm also building the front end)... but I'm still happier as an admin running reliable old Apache/FPM stacks at scale, and that's where the majority of my jobs are. Granted I mostly code in a "boring" non-tech, retail industry these days, but PHP is almost all I deal with in corporate jobs. And supply chain attacks are just not a thing.

One reason I asked this question is that I've never built a commercial Nodejs project from the ground up, just my own side projects which aren't particularly sensitive targets... but I'm trying to choose between Nodejs and PHP for a new client's business app which is somewhat sensitive. I'd be a lot more excited to write it in Nodejs, but looking down the road at having to maintain it securely for years I'm not sure. The Nodejs environment and keeping on top of dependencies feels risky right now in a way that's inclining me to use the old familiar PHP.

It just struck me as I wrote this that there's a lot I do in PHP that's just part of the language or default plugins, where almost every one of those things requires choosing NPM packages in Nodejs. Even simple stuff like talking to a database or managing sessions or setting up sockets. And the NPM packages get deprecated and renamed, sometimes there are two with very similar names by different authors and it's easy to miss a dash or something. Maybe I'm answering my own question here..

I don't think stuff life talking to a database is actually the problem in Node.js, I think you can trust mongo/mysql packages in NPM just as much as in PHP if you choose the right versions parameters in your package.json.

The packages/package manager are not the problem, it's more about the bad habits that you start to get when coding with Node/NPM, basically for every function you write, 9 times out of 10 you can just import a package after 1 import and a command, and so you start to have 200 potential liabilities because you became too lazy to code because it's really easy.

But if you stay at least a bit vigilant it's just as safe to use Node.js(or even safer).

I think it's really mostly about bad habits rather than the lack of functionality in the language.

Node js has ridiculously large dependancy trees. There is is this joke that a hello world program in NodeJS is only complete when it has 200 dependancies. If one of those many npm modules has a backdoor/vulnerability then you are screwed which is not the case for other languages.

There's more stuff worth breaking today in JS than there was twenty years ago in PHP, and more people that know how to do it.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact