alias npm='docker run --rm -it -v ${PWD}:${PWD} --net=host --workdir=${PWD} node:25-bookworm-slim npm'
  - No access to my env vars
  - No access to anything outside my current directory (usually a JS project).
  - No access to my .bashrc or other files.
Also I can recommend pnpm, it has stopped executing lifecycle scripts by default so you can whitelist which ones to run.
Because the counter-question could be: Why would anything but ssh or ansible need access to my ssh keys? Why would anything but firefox need access to the local firefox profiles? All of those can be mapped out with mount namespaces from the execution environment of most applications.
And sure, this is a blacklist approach, and a whitelist approach would be even stronger, but the blacklist approach to secure at least the keys to the kingdom is quicker to get off the ground.
Imagine you are in a 50-person team that maintains 10 JavaScript projects, which one is easier?
  - Switch all projects to `pnpm`? That means switching CI, and deployment processes as well
  - Change the way *you* run `npm` on your machine and let your colleagues know to do the same
The secure process change might take anywhere from a day to months.
Switch your projects once, done for all.
And npm can be configured to prevent install scripts to be run anyways:
> Consider adding ignore-scripts to your .npmrc project file, or to your global npm configuration.
But I do like your option to isolate npm for local development purposes.
> Switch all projects to `pnpm`?
Sorry; I am out of touch. Does pnpm not have these security problems? Do they only exist for npm?
As phiresky points out, you're still "download[ing] arbitrary code you are going to execute immediately afterwards" (in many/most cases), so it's far from foolproof, but it's sufficient to stop many of the attacks seen in the wild. For example, it's my understanding that last month's Shai-Hulud worm depended on postinstall scripts, so pnpm's restriction of postinstall scripts would have stopped it (unless you whitelist the scripts). But last month's attack on chalk, debug, et al. only involved runtime code, so measures like pnpm's would not have helped.
Further, you are welcome to use this alias on your CI as well to enhance the protection.
CI machines are very much high-value targets of interest.
Yes, but if I've got to configure that across the CI fleet as well as in my deploy system(s) in order to not get, and also be distributing malware, what's the difference between having to do that vs switching to pnpm in all the same places?
Or more explicitly, your first point is invalid. Whether you ultimately choose to use docker to run npm or switch to pnpm, it doesn't count to half-ass the fix and only tell your one friend on the team to switch, you have to get all developers to switch AND fix your CI system, AND also your deployment system (s) (if they are exposed).
This comment proffers no option on which of the two solutions should be preferred, just that the fix needs to made everywhere.
I won't execute that code directly on my machine. I will always execute it inside the Docker container. Why do you want to run commands like `vite` or `eslint` directly on your machine? Why do they need access to anything outside the current directory?
Most valuable data on your system for a malware author is login cookies and saved auth tokens of various services.
But it is true that work and personal machines have different threat vectors.
Because it means the hygiene is thrown over the fence in a post commit manner.
AI makes this worse because they also run them "over the fence".
However you run it, i want a human to hold accountability for the mainline committed code.
How does this throw hygiene over the fence?
is he just saying always run your code in a container?
> is he just saying always run your code in a container?
yes
> isn't that running things on your machine?
in this context where they're explicitly contrasted, it isn't running things "directly on my machine"
By default it directly runs code as part of the download.
By isolation there is at least a chance to do some form of review/inspection
> really just downloads arbitrary code you are going to
> execute immediately afterwards anyways?
I don't want to stereotype, but this logic is exactly why javascript supply chain is in the mess its in.
If you want to protect your machine from malicious dependencies you must run everything in a sandbox all the time, not just during the installation phase. If you follow that advice then disabling post-install scripts is pointless.
The supply chain world is getting more dangerous by the minute and it feels like I'm watching a train derail in slow motion with more and more people buying into the idea that they're safe if they just disable post-install scripts. It's all going to blow up in our collective faces sooner or later.
Improving NPM's processes, having more companies auditing packages, changing the way NPM the tool works - that's all good but far from enough, it doesn't actually address the root vulnerability, which is that we're way too comfortable running other people's arbitrary code.
Containerization and strict permissions system by default seem to be where we're headed.
I have been doing it for weeks now with no issues.
If I had malicious intentions, I would probably typo squat popular plugins/lsps that will execute code automatically when their editor runs. A compromised neovim or vscode gives you plenty of user permissions, a full scripting language, ability to do http calls, system calls, etc. Most LSPs are installed globally, doesn't matter if you downloaded it via a docker command.
Running `npm` inside Docker does not solve this problem. However, running `npm` inside Docker does not make this problem worse either.
That's why I said running `npm` inside Docker reduces the attack surface of the malicious NPM packages.
Setting up a fully containerized development environment doesn't take a lot of effort and will provide the benefits you think you're getting here - that would be the "imperfect but good enough for the moment" kind of solution, this is just security theater.
Every time I make this point someone wants to have the "imperfect but better than nothing" conversation and I think that shows just how dangerous the situation is becoming. You can only say that in good conscience if you follow it up with "better than nothing ... until I figure out how to containerize my environment over the weekend"
What you can do, however, is to adapt to current threats, the same way adversaries adapt to countermeasures. Fully secure setups do not exist, and even if one existed, it would probably become obsolete very quickly. Like James Mickens said, whatever you do, you still can be "Mossad'ed upon". Should we give up implementing security measures then?
Thinking about security in a binary fashion and gatekeeping it ("this is not enough, this is will not protect you against X and Y") is, _in my opinion_, very detrimental.
If a supply chain attack would be a serious incident for you then you need to take meaningful actions to protect yourself. I'm trying to hold "you" (proponents of this idea) accountable because I don't want you to rationalize all of these actions that leave you wide open to future attacks in known, preventable ways and then pretend nobody could've seen this coming when it blows up in our face.
It's not "good enough" - it's negligence because you know that the hole is there, you know that the hackers know about it, you know how trivial it is to exploit, and yet we're arguing whether leaving this known vector open is "good enough" instead of taking the obvious next step.
Containers are very far away from "fully secure" setup, they suffer from escape vulnerabilities far more often than VMs, but their benefit is that they're lightweight and minimally obtrusive (especially for web development) and these days the integration with IDEs is so good you probably won't even notice the difference after a few days of adjusting to the new workflow.
You end up trading a bit of convenience for a lot of security - you're going to be reasonably well protected for the foreseeable future because the likelihood of someone pulling off a supply chain attack and burning a container escape 0-day on it is really low.
That should be good enough for most and if your developer machine needs more protection than this, I'll take a guess and say that your production security requirements are such that they require security review of all your dependencies before using them anyway.
With a VM you would get even more security but you would have to sacrifice a lot more convenience, so given the resistance to the less intrusive option this isn't even worth discussing right now.
How can you not see the nuance?
I use sandbox-run: https://github.com/sandbox-utils/sandbox-run
The above simple alias may work for node/npm, but it doesn't generalize to many other programs available on the local system, with resources that would need to be mounted into the container ...
Thanks. You are right, running inside Docker won't always work for local commands. But I am not even using local commands.
Infact, I have removed `yarn`, `npm`, and several similar tools already from my machine.
It is best to run them inside Docker.
> I use sandbox-run: https://github.com/sandbox-utils/sandbox-run
How does this work if my local command is a Mac OS binary? How will it run inside Docker container?
At the very least, you really need to add process isolation / namespacing as well - at which point it's going to be easier to just use the sandboxing / containerisation tool of your choice to manage it all for you.
If only :(
Coming from "make" with repeatable and predictable builds, I was appalled that you run this thing and you have no idea what it will download and what it will produce. Could be something different the next time you run it! Who knows!
I also found it bizarre that even for things that just generate CSS, you are expected to integrate it into your npm thing. I mean, generating CSS from a configuration is a function. It's a make recipe. Why does it need to be an npm library dependency with all the associated mess? I managed to work around it for a number of packages by freezing entire npm setups inside docker containers, which gave me reproducible builds — but it's a losing battle.
How does that work when enevitably those npm packages are shown to have vulnerabilites?
I don't think the old C/C++ way of relying on distro package managers would allow for the fast ecosystems people work nowadays.
Things are changing though, and people are pushing for more secure package managers with the same feature set as the old ones, which is possible.
I think this is the missing piece on the first wondering part of your comment. But I don't think we should be bashing the means without understanding the reasons
Did you then spend a month or two inspecting that setup? Did you do that after every dependency upgrade?
Also both NPM and PNPM already freeze dependencies for you by default without any arcane docker setups.
TBH, I never updated some of the setups. What's the point? Their job was to generate a CSS. Why would I want to upgrade dependencies or inspect that setup?
> arcane docker setups
I take issue with "arcane" — I have much more "arcane" setups than these :-)
Lowering the barrier to entry is not paying off, for sure.
Too lazy to write, too cheap to pay for it, that's half of open source.
Now what's going to dominate stackoverflow answers, thoughtful articles on how to program? Or gratis npm/uv installable libraries that hide the actual solution details in between tests and polyfills and readmes, that end up just download another dependency while contributing enough lines of code so that the author can safely put it in their resume and grift over the oss ecosystem to get a cushy 300k/yr job at an extended faang where they are in charge of an ad pixel tracker or yet another one of those wallet things that are just an IO proxy for money but they get to keep some comission if they spend enough money on ads to convince someone to use the thing once and then it becomes their main neo(not) bank* forever.
*for regulatory reasons we must not call it a bank, but it's a bank
What's the legitimate use case for a package install being allowed to run arbitrary commands on your computer?
Quote is from the researchers report https://www.koi.ai/blog/phantomraven-npm-malware-hidden-in-i...
edit: I was thinking of this other case that spawned terminals, but the question stands: https://socket.dev/blog/10-npm-typosquatted-packages-deploy-...
The paradigm itself has been in package managers since DEB and RPM were invented (maybe even Solaris packages before that? it's been a minute since I've Sun'd); it's not the same as NPM, a more direct comparison is the Arch Linux AUR - and the AUR has been attacked to try and inject malware all year (2025) just like NPM. As of the 26th (5 days ago) uploads are disabled as they get DDOSed again. https://status.archlinux.org/ (spirit: it's the design being attacked, pain shared between AUR and NPM as completely disparate projects).
More directly to an example: the Linux kernel package. Every Linux distribution I'm aware of runs a kernel package post-install script which runs arbitrary (sic) commands on your system. This is, of course, to rebuild any DKMS modules, build a new initrd / initramfs, update GRUB bootloader entries, etc. These actions are unique outputs to the destination system and can't be packaged.
I have no data in front of me, but I'd speculate 70% (?) of DEB/RPM/PKG packages include pre / post install/uninstall scriptlets, it's very common in the space and you see it everywhere in use.
The truth is npm, pip, rubygems, cargo and all the other programming language package managers are just fancier versions of the silly installation instructions you often find in README files that tell people to curl some script and pipe it into bash.
NPM etc. are a bit like Arch would be if everything was in AUR.
Personally, I think the issue is that it is too easy to create packages that people can then pull too easily. rpm and dpkg are annoying to write for most people and require some kind of (at least cursory) review before they can be installed on user's systems from the default repos. Both of these act as barriers against the kinds of lazy attacks we've seen in the past few months. Of course, no language package registry has the bandwidth to do that work, so Wild West it is!
I assume that it's heavily sandboxed, though, so it may be difficult to leverage.
[0] https://docs.swift.org/swiftpm/documentation/packagemanagerd...
[1] https://developer.apple.com/documentation/packagedescription
What’s needed is an entitlements system so a package you install doesn’t do runtime stuff like install crypto mining software. Even then…
So preventing lifecycle scripts certainly limits the number of packages that could be exploited to get access to the installing machine. It's common for javascript apps to have hundreds of dependencies, but only a handful of them will ever actually run as code on the machine that installed them.
And with node you get files and the ability run arbitrary code on arbitrary processes.
It pains me to remember that the reason LLMs write like this is because many humans did in the training data.
In about as much text, we could explain far better why and how NPM's behaviour is risky:
> When you install a package using `npm install`, NPM may also run arbitrary code from the package, from multiple hook scripts specified in `package.json`, before you can even audit the code.
They use proinstall script to fetch pre-built binaries, or compile from source if your environment isn't directly supported.
the npm version is decoupled from the binary version, when i want them locked together
A) maintainers don’t know any better and connect things with string and gum until it most works and ship it
B) people who are smart, but naive and think it will be different this time
C) package manager creators who think they’re creating something that hasn’t been done before, don’t look at prior art or failures, and fall into all of the same holes literally every other package manager has fallen into and will continue to fall into because no one in this industry learns anything.
To me the entire JavaScript ecosystem is broken. And a typo in your “npm -i” is sufficient to open up yourself for a supply-chain attack. Could the same happen with NuGet or Maven? Sure!
But at least in these languages and environments I have a huge Standard Library and very few dependencies to take. It makes me feel much more in control.
This limits the attack surface, when it comes to installing malicious dependencies, that npm happily installs for you.
So yes, I was wrong and my previous comment a hyperbole. A big problem is npm, and not JavaScript.
My point about the staggering amount of dependencies still holds though.
When I build backend in flask or Django, I specifically type the python packages that I need. But front end development seems like a Pandora box of vulnerabilities
When I downloaded wan2gp (python) it installed it install 211 packages.
I would be willing to bet attacks on linux upstream libraries are already happening in the same way as the js ecosystem.
And yeah I'm trusting my OS (Linux) and the libraries that is in their repository.
We could go deeper than that. What about hardware? None of it is open source.
Where does it end? What can we do about it?
But it is. Both C/C++ and Go are not at all like this.
I don’t know about Python but Rust ecosystem tends attract enthusiasts who make good single purpose packages but that are abandoned because maintainers move on, or sometimes forked due to minor disagreements similar to how Linux/unix is fragmented with tribal feuds.
Even your OS upstream packages could be tainted at this point.
It depends on the software being written, but if it's a product your business sells or otherwise has an essential dependency on, then the best model available right now is vendoring dependencies.
You still get all the benefits of standing on top of libraries and frameworks of choice, but you've introduced a single point of entry for externally authored code - there are many ways you can leverage that to good effect (vuln scans, licence audits, adding patch overlays etc etc) and you improved the developer experience - when they check out the code, ALL of the code to build and run the project is already present, no separate npm install step.
You can take this model quite a bit further and buy some really useful capabilities for a development team, like dependency upgrades because they're a very deliberate thing now, you can treat them like any other PR to your code base - you can review the changes of each upgrade easily.
There's challenges too - maybe your npm dep builds a native binary as part of it, you now need to provide that build infra / tooling, and very likely you also want robust build artifact and test caching to save wasting lots of time.
And those last two points have absolutely nothing to do with micro dependencies one way or the other.
You now have to audit the hundreds of dependencies. Each time you upgrade them.
Rust is compiled and source code doesn't weigh that much, you could have the compiler remove dead code.
And sometimes it's just better to review and then copy paste small utility functions once.
I get the impression that one driver to make microdependencies in rust is that code does weigh a lot because the rust compiler is so slow.
For a language with a focus on safety, it's a pretty bad choice
Some of the gaps feel huge, like no random, no time/date handling, and no async runtime. But but for most of them there are canonical packages that 95% of the ecosystem uses, with a huge amount of eyeballs on them. And sometimes a better solution does emerge, like jiff slowly replacing chrono and time for time/date handling.
Obviously this isn't the best solution from a security perspective. There would be less potential for supply chain attacks if everything was in the standard library. But that has to be weighed against the long-term usability of the language
NPM is a terrible ecosystem, and trying to defend its current state is a lost cause. The energy should be focused on how to fix that ecosystem instead of playing dumb telling people "it's all ok, look at other, also poorly designed, systems".
Don't forget that Rust's Cargo got heavily inspired by NPM, which is not something to brag about.[0]
> "Rust has absolutely stunning dependency management," one engineer enthused, noting that Rust's strategy took inspiration from npm's.
[0]https://rust-lang.org/static/pdfs/Rust-npm-Whitepaper.pdf
It is like the xz incident, except that each dependency you pull is maintained by a random guy on the internet. You have to trust every one of them to be genuine and that they won't fall into any social engineering attacks.
Oh, absolutely, there is no question about it. Fewer dependencies means less headache; and if you can get the number of your dependencies to zero, then you have won the internet.
Having a large standard library does reduce the number of dependencies, and you can go a long way using only well known dependencies.
Recently there is a trend towards minimal-dependency packages and I would certainly recommend auditing every package for its dependencies before using it.
> Unlike other npm clients, Bun does not execute arbitrary lifecycle scripts for installed dependencies, such as `postinstall` and `node-gyp` builds. These scripts represent a potential security risk, as they can execute arbitrary code on your machine.
https://bun.com/docs/guides/install/trusted
I've also found the Bun standard library is a nice curated set of features that reduces dependencies.
When I iterate with new versions of a package that I’ve never promoted anywhere, each version gets hundreds of downloads in the first day or two of being published.
86,000 people did not get pwnd, possibly even zero.
> Many of the dependencies used names that are known to be “hallucinated” by AI chatbots.
There’s more here than that.
I would not be surprised to find that 80%+ of those 86,000 people got pwned.
Somewhat related, I also have a small homelab running local services and every now and then I try a new technology. occasionally I’ll build a little thing that is neat and could be useful to someone else, but then I worry that I’m just a target for some bot to infiltrate because I’m not sophisticated enough to stop it.
Where do I start?
Vendoring dependencies (copying the package code into your project rather than using the package manager to manage it) can help - it won't stop a malicious package, but it will stop a package from turning malicious.
You can also copy the code you need from a dependency into your code (with a comment giving credit and a link to the source package). This is really useful if you just need some of the stuff that the package offers, and also forces you to read and understand the package code; great practice if you're learning.
I think we need a different solution that fixes the dependency bloat or puts more safeguards around package publishing.
The same goes for any other language with excessive third-party dependency requirements.
It's going to take a lot of people getting pwned to change these attitudes though
Do development, all of it, inside VMs or containers, either local or remote.
Use ephemeral credentials within said VMs, or use no credentials. For example, do all your git pulls on your laptop directly, or in a separate VM with a mounted volume that is then shared with the VM/containers where you are running dev tooling.
This has the added benefit of not only sandboxing your code, but also making your dev environments repeatable.
If you are using GitHub, use codespaces. If you are using gitlab, workspaces. If you are using neither, check out tools like UTM or Vagrant.
The fact I use nvm means a global install won’t cross accounts.
Im genuinely curious because I casually looked into it so that i could work on some hobby stuff over lunch on my work machine.
However I just assumed the performance wouldn't be too great.
Would love to hear how people are setup…
There's around 10-15% performance penalty for VMs (assuming you use arm64 guests), but the whole system is just so much faster and well built than anything Intel-based to day, that it more than compensates.
For Windows, it's lacking accelerated video drivers, but VMWare Fusion is an ok free alternative - I can totally play AAA games from last decade. Enjoy it until broadcom kills it.
Then, I removed the graphical settings, as I was aiming to use SSH instead of emulated TTY that comes ON by default with UTM (at that time).
Finally, I set up some basic scripting to turn the machine on and SSH into it as soon as sshd.service was available, which I don't have now, but the script finished with this:
(fish shell)
    while not ssh -p 2222 arch@localhost; sleep 2; end;
    virsh start arch-linux_testing && virsh qemu-monitor-command --hmp arch-linux_testing 'hostfwd_add ::2222-:22' && while not ssh -p 2222 arch@localhost; sleep 2; end;
    arch@archlinux ~> sudo systemctl mask systemd-time-wait-sync.service 
    arch@archlinux ~> sudo systemctl disable systemd-time-wait-sync.service
[1]: https://gitlab.archlinux.org/archlinux/arch-boxes/-/packages...
Pretty soon I liked using the environment so much that I got my work running on it. And when I change the environment, I can sync it to my other machine.
Though NixOS is particularly magical as a dev environment since you have a record of everything you've done. Every time I mess with postgres hb_conf or nginx or pcap or on my local machine, I think "welp, I'll never remember that I did that".
I still maintain pushing this back to library authors is the right thing to do instead of making this painful for literally millions of end-users. The friction of getting a package accepted into a critical mass of distributions is the point.
Neither is a security guarantee, but it does add a substantial extra barrier.
https://npmgraph.js.org/?q=hono
https://npmgraph.js.org/?q=zod
Recently I switched to Bun in part because many dependencies are already included (db driver, s3 client, etc) that you'd need to download with Node or Deno.
Any package that includes a CLI version in the library should have it's dev shamed. Usually that adds 10-20 packages. Those 2 things, a library that provides some functionality, and a CLI command that lets you use the library from the command line, SHOULD NEVER BE MIXED.
The library should be its own package without the bloat of the command line crap
(2) Choose low dependency packages
Example: commander has no dependencies, minimist now has no dependencies. Some other command line parsers used to have 10-20 dependencies.
(3) Stop using packages when you can do it yourself in 1-2 lines of JS
You don't need a package to copy files. `fs.copyFileSync` will copy a file for. `fs.cpSync` will copy a tree, `child_process.spawn` will spawn a process. You don't need some package to do these things. There's plenty of other examples where you don't need a package.
After your little rant you point out Commander has zero dependencies. So I don’t know what’s up with you.
If the library you’re building has anything with application lifecycle, particularly bootstrapping, then having a CLI with one dependency is quite handy for triage. Most especially for talking someone else through triage when for instance I was out and there was a production issue.
Which is why half the modules I worked on at my last place ended up with a CLI. They are, as a rule, read mostly. Which generally doesn’t require an all caps warning.
Does every module need one of those? No. But if your module is meant as a devDependency, odds are good it might. And if it’s bootstrapping code, then it might as well.
> should have it's dev shamed
Oh I feel embarrassed right now. But not for me.
For the case of general software, "Don't use node" would be my advice, and by extension any packaging backend without external audit and validation. PyPI has its oopses too, Cargo is theoretically just as bad but in practice has been safe.
The gold standard is Use The Software Debian Ships (Fedora is great too, arch is a bit down the ladder but not nearly as bad as the user-submitted madness outside Linux).
But it seems like your question is about front end web development, and that's not my world and I have no advice beyond sympathy.
> occasionally I’ll build a little thing that is neat and could be useful to someone else, but then I worry that I’m just a target for some bot
Pretty much that's the problem exactly. Distributing software is hard. It's a lot of work at a bunch of different levels of the process, and someone needs to commit to doing it. If you aren't willing to commit your time and resources, don't distribute it in a consumable way (obviously you can distribute what you built with it, and if it's appropriately licensed maybe someone else will come along and productize it).
NPM thought they could hack that overhead and do better, but it turns out to have been a moved-too-fast-and-broke-things situation in hindsight.
One obvious further mitigation for Python is to configure your package installer to require pre-built wheels, and inspect the resulting environment prior to use. Of course, wheels can contain all sorts of compiled binary blobs and even the Python code can be obfuscated (or even missing, with just a compiled .pyc file in its place); but at least this way you are protected from arbitrary code running at install time.
You don't get secure things for free, you have to pay for that by doing things like "import and audit software yourself" or even "write simple utilities from scratch" on occasion.
IME Debian is falling behind on security fixes.
FWIW, the subject at hand here isn't accidentally introduced security bugs (which affect all software and aren't well treated by auditing and testing). It's deliberately malicious malware appearing as a dependency to legitimate software.
So the use case here isn't Heartbleed, it's something like the xz-utils trojan. I'll give you one guess as to who caught that.
I think security controls on macOS have been trending in the right direction to tackle these types of things comprehensively with secure domains, sandboxing, etc. but there is always a war of how much friction is too much when it comes to security.
We saw the same thing with 2SV where people were vehemently against it, and now many are clamoring that it should be the only way to be able to do things like publish packages (I agree! I have no issue jumping through some extra hoops when I publish something a million people will install).
This might be a hot take but I think a lot of loud mouths with their personal preferences have been holding security in this space back for a while, and recently people seem to be getting tired of it and pushing through. The engineering leadership that won't just make these types of high impact security decisions because it might irritate a handful of highly opinionated workflows is unfortunate!
I found it very interesting that they used common AI hallucinated package names.
https://github.com/evilsocket/opensnitch/discussions/1290
that malware campaign is still active.
Overlay version control systems like NPM, Cargo, etc. and their harebrained schemes involving "lockfiles" to paper over their deficiencies have evidently totally destroyed not just folks' ability to conceive of just using an SCM like Git or Mercurial to manage source the way that they're made for without introducing a second, half-assed, "registry"-dependent VCS into the mix, but also destroyed the ability to recognize when a comment on the subject is dripping in the most obvious, easily detectable irony.
Maybe in a perfect world, we’d all use a better VCS whose equivalent of submodules actually could do that job. We are not in that world yet.
Go-style vendoring does dump everything into a directory but that has other downsides. I also question how effectively you can audit dependencies this way -- C developers don't have to do this unless there's a problem they're debugging, and at least for C it is maybe a tractible problem to audit your entire dependency graph for every release (of which there are relatively few).
Unfortunately IMHO the core issue is that making the packaging and shipping of libraries easy necessarily leads to an explosion of libraries with no mechanism to review them -- you cannot solve the latter without sacrificing the former. There were some attempts to crowd-source auditing as plugins for these package managers but none of them bore fruit AFAIK (there is cargo-audit but that only solves one part of the puzzle -- there really needs to be a way to mark packages as "probably trustworthy" and "really untrustworthy" based on ratings in a hard-to-gamify way).
That is, when a security issue is found, regardless of supply chain tooling one would update.
That there is a little cache/mirror thing in the middle is of little consequence in that case.
And for all other cases the blessed versions in your mirror are better even if not latest.
I have used Node, I would not go near the NPM auto install Spyware service.
How is it possible that people keep this service going, when it has been compromised so regularly?
How's it possible that people keep using it?
I don't usually get to say 'I told you so' within 24 hours of a warning, but JS is special like that.
The problem is we've been coasting on an era where blind trust was good enough an programming was niche enough.
In c++, most people wouldn't publish a library that does the equivalent of (1 == value % 2). Even if they did, almost no one would use it. For npm, that library will not only exist, it will have several dependencies and millions of downloads