Remix.run Logo
'No Way to Prevent This,' Says Only Package Manager Where This Regularly Happens(kevinpatel.xyz)
100 points by alligatorplum 2 hours ago | 28 comments
827a 4 minutes ago | parent | next [-]

There is no legitimate reason why postinstall scripts need to exist. The npm team needs to grow up and declare "starting with npm version whatever, npm will only run postinstall scripts for versions of packages published before ${today}".

btown 40 minutes ago | parent | prev | next [-]

For those unfamiliar with the context: https://en.wikipedia.org/wiki/%27No_Way_to_Prevent_This,%27_...

Modified3019 36 minutes ago | parent | next [-]

Same vibe: https://www.youtube.com/watch?v=lOTyUfOHgas

yieldcrv 18 minutes ago | parent | prev [-]

the onion article is still up could link that

fragmede 9 minutes ago | parent [-]

https://theonion.com/no-way-to-prevent-this-says-only-nation...

aselimov3 32 minutes ago | parent | prev | next [-]

What are the actual guarantees that go/Rust make that Python/npm don’t? It seems like it might just be that Python/npm are juicier targets? I’m starting to try and avoid all third party packages

lostglass 6 minutes ago | parent | next [-]

To be honest Rust has the exact same supply chain attack pattern - it's just newer and more maintained at the moment. Give it a decade.

nothinkjustai 4 minutes ago | parent [-]

Rust doesn’t have post install scripts

deeebug a minute ago | parent | next [-]

They have build.rs (https://doc.rust-lang.org/cargo/reference/build-scripts.html)

fabrice_d a minute ago | parent | prev | next [-]

It has build.rs that will run as soon as you compile the dependency. That's not the same thing but pretty close to a post install script: it's very likely to run.

tasn a minute ago | parent | prev [-]

It has build.rs, which has essentially the same problems.

panzi 8 minutes ago | parent | prev | next [-]

Last I checked npm had 2FA for publishing, but cargo didn't. I don't think cargo is any better than npm, just not that of an attractive target.

jollyllama 8 minutes ago | parent | prev | next [-]

> It seems like it might just be that Python/npm are juicier targets?

Attackers go where the victims are. Frontend is a monoculture with the vast majority using NPM; backend, less so. This isn't an excuse for NPM, but another strike against it.

You could also argue that the attacks make a deeper point about frontend vs backend devs, but I won't go there.

cookiengineer 24 minutes ago | parent | prev | next [-]

I suppose that go's go:generate workflow can also be abused to land a worm like the ones spreading via npm, as you can build programs that just scrape the whole hard drive for git projects and patch the go.mod dependencies there, and you could also just write this in go as a toolchain script, for example.

NPM's achilles is the pre/postinstall step which can run arbitrary commands and shell scripts without the user having any way to intervene.

Dependencies must be run in isolated chroot sandboxes or better, inside containers. That would be the only way to mitigate this problem, as the filesystem of the operating system must be separated from the filesystem of the development workflow.

On top of that most host based firewalls are per-binary instead of per-cmdline. That leads to the warnings and rules relying on that e.g. "python" or "nodejs" getting network access allowlisted, instead of say "nodejs myworm.js". So firewalls in general are pretty useless against this type of malware.

yegle 8 minutes ago | parent | next [-]

`go:generate` is for the package provider, the command never runs when someone `go install` or `go get` the package.

xena 8 minutes ago | parent | prev [-]

go:generate is done at dev time, not at build time.

cookiengineer 6 minutes ago | parent [-]

Actually bindings are usually generated like that, at build time (though with a build cache that nobody knows how it actually corrupts all the time).

Examples: webview/webview, webkit, cilium/ebpf and most CGo projects that I have seen.

jiggawatts a minute ago | parent | prev [-]

Generally, other package managers aren't great either. Notably, crates.io / cargo has some of the same people behind it as NPM and the verbiage of their excuses is oddly similar.

Something fascinating about the design and architecture of programming languages and their surrounding ecosystems is the enormous leverage that they provide to the "core team":

For every 1 core language developer[1]...

... there may be 1,000 popular package developers...

... for which there may be 1,000,000 developers writing software...

... for over 1,000,000,000 users.

This means that for every error and for every quality corner cut at the top of that pyramid is massively magnified at the lower tiers. A security vulnerability in a "top one thousand" package like log4j can cause billions of dollars in economic damage, man-centuries of remediation effort, etc.

However, bizarrely, the funding at the top two levels is essentially a pittance! Most such projects are charities, begging for spare change with hat in hand on a street corner. Top libraries are often volunteer efforts. cough-OpenSSL-cough.

The result is that the people most empowered to fix the issues are the least funded to do so.

This is why NPM, Crates.io, etc... flatly refuse to do even the most basic security checks like adding namespaces and verifying the identity of major publishers like Google, Microsoft, and the like.

That's a non-zero amount of effort, and no matter how trivial to implement technically and now cheap to police, it would likely blow their tiny budget of unreliable donations.

The exceptions to this rule are package-managers with robust financial backing, such as NuGet, which gets reliable funding from Microsoft and supports their internal (for-profit!) workflows almost as much as it does external "free" users.

"Free and open" is wonderful and all, but you get what you pay for.

[1] Most of us can name them off the top of our heads: Guido van Rossum, Larry Wall, Kerningham & Richie, etc.

yegle 6 minutes ago | parent | prev | next [-]

Vendorizing using git submodule should be a robust mitigation for this problem.

exabrial 30 minutes ago | parent | prev | next [-]

I really don't understand why the npm project cannot embrace PGP as an ambulatory 'good enough' solution.

loloquwowndueo 28 minutes ago | parent | next [-]

The NIH mentality in the ecosystem would result in a JavaScript pgp library which itself would be an npm package and subject to supply chain attacks. lol.

panzi 11 minutes ago | parent [-]

A good part of it is already implemented in web crypto, which is supported by browsers and node. There is a chance that npm could implement something there without extra dependencies. Maybe I'm too optimistic?

Gigachad 15 minutes ago | parent | prev [-]

Would that help? Most of these recent attacks, the attackers have gained access to the system that builds the packages. So it would have just signed the malicious build the same.

p-e-w 34 minutes ago | parent | prev [-]

With the recent high-profile attacks on PyPI packages, it’s no longer true that npm is the “only package manager where this regularly happens”.

In fact, pip is much more dangerous than npm because it lacks a lockfile. uv fixes that, but adoption is proceeding at a snail’s pace.

esafak a few seconds ago | parent | next [-]

Apparently it does now: https://packaging.python.org/en/latest/specifications/pylock...

https://pip.pypa.io/en/stable/cli/pip_lock/

(Just use uv!)

godzillabrennus 15 minutes ago | parent | prev | next [-]

UV adoption is happening, though. NPM is still the only name in town.

manquer 7 minutes ago | parent [-]

[delayed]

fragmede 7 minutes ago | parent | prev [-]

I don't know about snails, but everything I'm in contact with has moved over to uv, and I can't imagine I'm the only one.