Most active commenters
  • koakuma-chan(10)
  • lucideer(8)
  • simiones(6)
  • johnisgood(6)
  • cxr(5)
  • skydhash(5)
  • yawaramin(5)
  • WD-42(4)
  • burntsushi(4)
  • pixl97(4)

←back to thread

1208 points jamesberthoty | 194 comments | | HN request time: 2.979s | source | bottom
1. codemonkey-zeta ◴[] No.45261026[source]
I'm coming to the unfortunate realizattion that supply chain attacks like this are simply baked into the modern JavaScript ecosystem. Vendoring can mitigate your immediate exposure, but does not solve this problem.

These attacks may just be the final push I needed to take server rendering (without js) more seriously. The HTMX folks convinced me that I can get REALLY far without any JavaScript, and my apps will probably be faster and less janky anyway.

replies(18): >>45261086 #>>45261121 #>>45261140 #>>45261165 #>>45261220 #>>45261265 #>>45261285 #>>45261457 #>>45261571 #>>45261702 #>>45261970 #>>45262601 #>>45262619 #>>45262851 #>>45267210 #>>45268405 #>>45269073 #>>45273081 #
2. petcat ◴[] No.45261086[source]
Rendering template partials server-side and fetching/loading content updates with HTMX in the browser seems like the best of all worlds at this point.
replies(1): >>45261097 #
3. koakuma-chan ◴[] No.45261097[source]
Until you need to write JavaScript?
replies(3): >>45261143 #>>45261161 #>>45261240 #
4. philipwhiuk ◴[] No.45261121[source]
HTMX is full of JavaScript. Server-side-rendering without JavaScript is just back to the stuff Perl and PHP give you.
replies(3): >>45261273 #>>45261514 #>>45262149 #
5. jddj ◴[] No.45261140[source]
Is the difference between the number of dev dependencies for eg. VueJs (a JavaScript library for marshalling Json Ajax responses into UI) and Htmx (a JavaScript library for marshalling html Ajax responses into UI) meaningful?

There is a difference, but it's not an order of magnitude and neither is a true island.

Granted, deciding not to use JS on the server is reasonable in the context of this article, but for the client htmx is as much a js lib with (dev) dependencies as any other.

https://github.com/bigskysoftware/htmx/blob/master/package.j...

https://github.com/vuejs/core/blob/main/package.json

replies(1): >>45271294 #
6. baq ◴[] No.45261143{3}[source]
Which should be much less than what’s customary?
7. ehnto ◴[] No.45261161{3}[source]
But that's the neat part, you don't!
replies(1): >>45261170 #
8. tarruda ◴[] No.45261165[source]
AFAICT, the only thing this attack relies on, is the lack of scrutiny by developers when adding new dependencies.

Unless this lack of scrutiny is exclusive to JavaScript ecosystem, then this attack could just as well have happened in Rust or Golang.

replies(6): >>45261185 #>>45261224 #>>45261255 #>>45262968 #>>45267488 #>>45274187 #
9. koakuma-chan ◴[] No.45261170{4}[source]
Until you have to.
replies(1): >>45261880 #
10. hsbauauvhabzb ◴[] No.45261185[source]
JavaScript does have some pretty insane dependency trees. Most other languages don’t have anywhere near that level of nestedness.
replies(4): >>45261308 #>>45261471 #>>45261685 #>>45261896 #
11. reactordev ◴[] No.45261220[source]
Until you go get malware

Supply chain attacks happen at every layer where there is package management or a vector onto the machine or into the code.

What NPM should do if they really give a shit is start requiring 2FA to publish. Require a scan prior to publish. Sign the package with hard keys and signature. Verify all packages installed match signatures. Semver matching isn’t enough. CRC checks aren’t enough. This has to be baked into packages and package management.

replies(6): >>45261275 #>>45261601 #>>45261616 #>>45261805 #>>45262090 #>>45263276 #
12. ◴[] No.45261224[source]
13. bdcravens ◴[] No.45261240{3}[source]
Then write it. Javascript itself isn't the problem, naive third-party dependencies are.
replies(1): >>45263178 #
14. coldpie ◴[] No.45261255[source]
I don't know Go, but Rust absolutely has the same problem, yes. So does Python. NPM is being discussed here, because it is the topic of the article, but the issue is the ease with which you can pull in unvetted dependencies.

Languages without package managers have a lot more friction to pull in dependencies. You usually rely on the operating system and its package-manager-humans to provide your dependencies; or on primitive OSes like Windows or macOS, you package the dependencies with your application, which involves integrating them into your build and distribution systems. Both of those involve a lot of manual, human effort, which reduces the total number of dependencies (attack points), and makes supply-chain issues like this more likely to be noticed.

The language package managers make it trivial to pull in dozens or hundreds of dependencies, straight from some random source code repository. Your dependencies can add their own dependencies, without you ever knowing. When you have dozens or hundreds of unvetted dependencies, it becomes trivial for an attacker to inject code they control into just one of those dependencies, and then it's game over for every project that includes that one dependency anywhere in their chain.

It's not impossible to do that in the OS-provided or self-managed dependency scenario, but it's much more difficult and will have a much narrower impact.

replies(1): >>45262448 #
15. lucideer ◴[] No.45261265[source]
> I'm coming to the unfortunate realizattion that supply chain attacks like this are simply baked into the modern JavaScript ecosystem.

I see this odd take a lot - the automatic narrowing of the scope of an attack to the single ecosystem it occurred in most recently, without any real technical argument for doing so.

What's especially concerning is I see this take in the security industry: mitigations put in place to target e.g. NPM, but are then completely absent for PyPi or Crates. It's bizarre not only because it leaves those ecosystems wide open, but also because the mitigation measures would be very similar (so it would be a minimal amount of additional effort for a large benefit).

replies(7): >>45261389 #>>45261408 #>>45261464 #>>45262010 #>>45263376 #>>45266913 #>>45270888 #
16. bdcravens ◴[] No.45261273[source]
I don't think the point is to avoid Javascript, but to avoid depending on a random number of third-parties.

> Server-side-rendering without JavaScript is just back to the stuff Perl and PHP give you.

As well as Ruby, Python, Go, etc.

17. lycopodiopsida ◴[] No.45261275[source]
> Until you go get malware

While technically true, I have yet to see Go projects importing thousands of dependencies. They may certainly exist, but are absolutely not the rule. JS projects, however...

We have to realize, that while supply chain attacks can happen everywhere, the best mitigations are development culture and solid standard library - looking at you, cargo.

I am a JS developer by trade and I think that this ecosystem is doomed. I absolutely avoid even installing node on my private machine.

replies(1): >>45261371 #
18. everdrive ◴[] No.45261285[source]
Javascript is badly over-used and over-depended on. So many websites just display text and images, but have extremely heavy javascript libraries because that's what people know and that is part of the default, and because it enables all the tracking that powers the modern web. There's no benefit to the user, and we'd be better off without these sites existing if there were really no other choice but to use javascript.
replies(2): >>45262111 #>>45263554 #
19. staminade ◴[] No.45261308{3}[source]
Don't they?

I just went to crates.io and picked a random newly updated crate, which happened to be pixelfix, which fixes transparent pixels in pngs.

It has six dependencies and hundreds of transient dependencies, may of which appear to be small and highly specific a la left-pad.

https://crates.io/crates/pixelfix/0.1.1/dependencies

Maybe this package isn't representative, but it feels pretty identical to the JS ecosystem.

replies(1): >>45261384 #
20. homebrewer ◴[] No.45261371{3}[source]
Here's an example off the top of my mind:

https://github.com/go-gitea/gitea/blob/main/go.sum

replies(2): >>45261541 #>>45261845 #
21. koakuma-chan ◴[] No.45261384{4}[source]
It depends on `image` which in turn depends on a number of crates to handle different file types. If you disable all `image` features, it only has like 5 dependencies left.
replies(1): >>45261462 #
22. woodruffw ◴[] No.45261389[source]
Could you say more about what mitigations you’re thinking of?

I ask because think the directionality is backwards here: I’ve been involved in packaging ecosystem security for the last few years, and I’m generally of the opinion that PyPI has been ahead of the curve on implementing mitigations. Specifically, I think widespread trusted publishing adoption would have made this attack less effective since there would be fewer credentials to steal, but npm only implemented trusted publishing recently[1]. Crates also implemented exactly this kind of self-scoping, self-expiring credential exchange ahead of npm.

(This isn’t to malign any ecosystem; I think people are also overcorrect in treating this like a uniquely JavaScript-shaped problem.)

[1]: https://github.blog/changelog/2025-07-31-npm-trusted-publish...

replies(1): >>45265093 #
23. kees99 ◴[] No.45261408[source]
I agree other repos deserve a good look for potential mitigations as well (PyPI too, has a history of publishing malicious packages).

But don't brush off "special status" of NPM here. It is unique in that JS being language of both front-end and back-end, it is much easier for the crooks to sneak in malware that will end up running in visitor's browser and affect them directly. And that makes it a uniquely more attractive target.

replies(1): >>45261968 #
24. Aeolun ◴[] No.45261457[source]
Why is this inevitable? If you use only easily verifyable packages you’ve lost nothing. The whole concept of npm automatically executing postinstall scripts was fixed when my pnpm started asking me every time a new package wanted to do that.
25. staminade ◴[] No.45261462{5}[source]
And all those 5 remaining dependencies have lots of dependencies of their own. What's your point?
replies(1): >>45261588 #
26. weinzierl ◴[] No.45261464[source]
Which mitigations specifically are in npm but not in crates.io?

As far as I know crates.io has everything that npm has, plus

- strictly immutable versions[1]

- fully automated and no human in the loop perpetual yanking

- no deletions ever

- a public and append only index

Go modules go even further and add automatic checksum verification per default and a cryptographic transparency log.

Contrast this with docker hub for example, where not even npm's basic properties hold.

So, it is more like

docker hub ⊂ npm ⊂ crates.io ⊂ Go modules

[1] Nowadays npm has this arguably too

replies(2): >>45263419 #>>45265052 #
27. cxr ◴[] No.45261471{3}[source]
It's not possible for a language to have an insane dependency tree. That's an attribute of a codebase.
replies(2): >>45262259 #>>45262954 #
28. hosh ◴[] No.45261514[source]
Do you count LiveView (Elixir) in that assessment?
29. mayama ◴[] No.45261541{4}[source]
Half of go.sum dependencies generally are multiple versions of same package. 400 still a lot, but a huge project like gitea might need them I guess.

> cat go.sum |awk '{print $1}' | sort |uniq |wc -l

431

> wc -l go.sum

1156 go.sum

30. hoppp ◴[] No.45261571[source]
They are. Any language that depends heavily on package managers and lacks a standard lib is vulnerable to this.

At some point people need to realize and go back to writing vanilla js, which will be very hard.

The rust ecosystem is also the same. Too much dependence on packages.

An example of doing it right is golang.

replies(5): >>45261629 #>>45261913 #>>45263129 #>>45263714 #>>45271822 #
31. koakuma-chan ◴[] No.45261588{6}[source]
> What's your point?

Just defending Rust.

> 5 remaining dependencies have lots of dependencies of their own.

Mostly well-known crates like rayon, crossbeam, tracing, etc.

replies(1): >>45262478 #
32. cxr ◴[] No.45261601[source]
If NPM really cared, they'd stop recommending people use their poorly designed version control system that relies on late-fetching third-party components required by the build step, and they'd advise people to pick a reliable and robust VCS like Git for tracking/storing/retrieving source code objects and stick to that. This will never happen.

NPM has also been sending out nag emails for the last 2+ years about 2FA. If anything, that constituted an assist in the attack on the Junon account that we saw a couple weeks ago.

replies(1): >>45261851 #
33. psychoslave ◴[] No.45261616[source]
How will multi-factor-authentication prevent such a supply chain issue?

That is, if some attacker create some dummy trivial but convenient package and 2 years latter half the package hub depends on it somehow, the attacker will just use its legit credential to pown everyone and its dog. This is not even about stilling credentials. It’s a cultural issue with bare blind trust to use blank check without even any expiry date.

https://en.wikipedia.org/wiki/Trust,_but_verify

replies(1): >>45262205 #
34. rs186 ◴[] No.45261629[source]
Python and Rust both have decent std lib, but it is just a matter of time before this happens in thoae ecosystems. There is nothing unique about this specific attack that could only happen in JavaScript.
35. rixed ◴[] No.45261685{3}[source]
This makes little sense. Any popular language with a lax package management culture will have the exact same issue, this has nothing to do with JS itself. I'm actually doing JS quasi exclusively these days, but with a completely different tool chain, and feel totally unconcerned by any of these bi-weekly NPM scandals.
36. brazukadev ◴[] No.45261702[source]
Not for the frontend. esm modules work great nowadays with import maps.
37. floydnoel ◴[] No.45261805[source]
NPM does require 2FA to publish. I would love a workaround! Isn't it funny that even here on HN, misinformation is constantly being spread?
replies(3): >>45262306 #>>45268926 #>>45271279 #
38. EdiX ◴[] No.45261845{4}[source]
I think you are reading that wrong, go.sum isn't a list of dependencies it's a list of checksums for modules that were, at some point, used by this module. All those different versions of the same module listed there, they aren't all dependencies, at most one of them is.

Assuming 'go mod tidy' is periodically run go.mod should contain all dependencies (which in this case seems to be shy of 300, still a lot).

39. ptx ◴[] No.45261851{3}[source]
NPM lock files seem to include hashes for integrity checking, so as long as you check the lock file into the VCS, what's the difference?
replies(1): >>45262037 #
40. speed_spread ◴[] No.45261880{5}[source]
The only way to win is not to play.
replies(1): >>45262311 #
41. BrouteMinou ◴[] No.45261896{3}[source]
Rust is working on that. It's not far behind right now, leave it a couple of years.
42. BrouteMinou ◴[] No.45261913[source]
C#, Java, and so on.
43. znort_ ◴[] No.45261968{3}[source]
npm in itself isn't special at all, maybe the userbase is but that's irrelevant because the mitigation is pretty easy and 99.9999% effective, works for every package manager and boils down to:

1- thoroughly and fully analyze any dependency tree you plan to include 2- immediately freeze all its versions 3- never update without very good reason or without repeating 1 and 2

in other words: simply be professional, face logical consequences if you aren't. if you think one package manager is "safer" than others because magic reasons odds are you'll find out the hard way sooner or later.

replies(3): >>45262164 #>>45262676 #>>45274141 #
44. jeswin ◴[] No.45261970[source]
Traditional JS is actually among the safest environments ever created. Every day, billions of devices run untrusted JS code, and no other platform has seen sandboxed execution at such scale. And in nearly three decades, there have been very few incidents of large successful attacks on browser engines. That makes the JS engine derived from browsers the perfect tool to build a server side framework out of.

However, processes and practices around NodeJS and npm are in dire need of a security overhaul. leftpad is a cultural problem that needs to be addressed. To start with, snippets don't need to be on npm.

replies(6): >>45262184 #>>45262208 #>>45262220 #>>45262223 #>>45262238 #>>45264048 #
45. WD-42 ◴[] No.45262010[source]
I mostly agree. But NPM is special, in that the exposure is so much higher. The hypothetical python+htmx web app might have 10s of dependencies (including transitive) whereas your typical Javascript/React will have 1000s. All an attacker needs to do is find one of many packages like TinyColor or Leftpad or whatever and now loads of projects are compromised.
replies(3): >>45262394 #>>45262453 #>>45263490 #
46. cxr ◴[] No.45262037{4}[source]
Wrong question; NPM isn't bedrock. The question to be answered if there is no difference is, "In that case, why bother with NPM?"
47. HillRat ◴[] No.45262090[source]
Sign the package with hard keys and signature.

That's really the core issue. Developer-signed packages (npm's current attack model is "Eve doing a man-in-the-middle attack between npm and you," which is not exactly the most common threat here) and a transparent key registry should be minimal kit for any package manager, even though all, or at least practically all, the ecosystems are bereft of that. Hardening API surfaces with additional MFA isn't enough; you have to divorce "API authentication" from "cryptographic authentication" so that compromising one doesn't affect the other.

replies(1): >>45266043 #
48. mrweasel ◴[] No.45262111[source]
NPM does seem vastly over represented in these type of compromises, but I don't necessarily think that e.g. pypi is much better in terms of security. So you could very well be correct that NPM is just a nicer, perhaps bigger, target.

If you can sneak malware into a JavaScript application that runs in millions of browsers, that's a lot more useful that getting a some number servers running a module as part of a script, who's environment is a bit unknown.

Javascript really could do with a standard library.

49. norman784 ◴[] No.45262149[source]
HTMX does not have external dependencies, only dev dependencies, reducing the attack surface.
50. tbrownaw ◴[] No.45262164{4}[source]
Your item #1 there may be simple, but that's not the same as being easy.
replies(1): >>45270695 #
51. spankalee ◴[] No.45262184[source]
Sandboxing doesn't do any good if the malicious code and target data are in the same sandbox, which is the whole point of these supply-chain attacks.
replies(3): >>45262918 #>>45266847 #>>45267459 #
52. deanc ◴[] No.45262205{3}[source]
That's an entirely different issue compared to what we're seeing here. If an attacker rug-pulls of course there is nothing that can be done about that other than security scanning. Arguably some kind of package security scanning is a core-service that a lot of organisations would not think twice about paying npm for.
replies(1): >>45263151 #
53. kortilla ◴[] No.45262208[source]
None of those security guarantees matter when you take out the sandbox, which is exactly what server-side JS does.

The isolated context is gone and a single instance of code talking to an individual client has access to your entire database. It’s a completely different threat model.

replies(1): >>45262925 #
54. WD-42 ◴[] No.45262220[source]
Javascript doesn't have a standard library, until it does the 170 million[1] weekly downloads of packages like UUID will continue. You can't expect people to re-write everything over and over.

[1]https://www.npmjs.com/package/uuid

replies(5): >>45262335 #>>45262791 #>>45263174 #>>45263227 #>>45264429 #
55. mewpmewp2 ◴[] No.45262223[source]
Interestingly AI should be able to help a lot with desire to load those snippets.

What I'm wondering if it would help the ecosystem, if you were able to rather load raw snippets into your codebase, and source control as opposed to having them as dependencies.

So e.g. shadcn component pasting approach.

For things like leftPad, cli colors and others you would just load raw typescript code from a source, and there you would immediately notice something malicious or during code reviews.

You would leave actual npm packages to only actual frameworks / larger packages where this doesn't make sense and expect higher scrutiny, multi approvals of releases there.

56. skydhash ◴[] No.45262238[source]
I think the smallest C library I’ve seen was a single file to include on your project if you want terminal control like curses on windows. A lot of libraries on npm (and cargo) should be gist or a blog post.
replies(2): >>45266658 #>>45272307 #
57. WD-42 ◴[] No.45262259{4}[source]
Maybe the language should have a standard library then.
replies(1): >>45262486 #
58. cxr ◴[] No.45262306{3}[source]
NPM does not require two-factor authentication. If two-factor authentication is enabled for your account and you wish to disable it, this explains how to do that if allowed by your organization:

<https://docs.npmjs.com/configuring-two-factor-authentication...>

replies(1): >>45264888 #
59. koakuma-chan ◴[] No.45262311{6}[source]
Let me quit my job real quick. The endgame is probably becoming a monk, no kidding.
replies(1): >>45271982 #
60. skydhash ◴[] No.45262335{3}[source]
You have the DOM and Node APIs. Which I think cover more than C library or Common Lisp library. Adding direct dependencies is done by every project. The issue is the sprawling deps tree of NPM and JS culture.

> You can't expect people to re-write everything over and over.

That’s the excuse everyone is giving, then you see thousands of terminal libraries and calendar pickers.

replies(2): >>45263264 #>>45274064 #
61. skydhash ◴[] No.45262394{3}[source]
Stuff like Babel, React, Svelte, Axios, Redux, Jest… should be self contained and not depend on anything other than being a peer dependency. They are core technological choices that happens early in the project and is hard or impossible to replace afterwards.
replies(1): >>45263639 #
62. skydhash ◴[] No.45262448{3}[source]
If you try installing npm itself on debian, you would think you are downloading some desktop environment. So many little packages.
63. johnisgood ◴[] No.45262453{3}[source]
Well, your typical Rust project has over 1000 dependencies, too. Zed has over 2000 in release mode.
replies(2): >>45263514 #>>45265047 #
64. johnisgood ◴[] No.45262478{7}[source]
You cannot defend Rust if this is reality.

Any Rust project I have ever compiled pulled in over 1000 dependencies. Recently it was Zed with its >2000 dependencies.

replies(1): >>45262797 #
65. skydhash ◴[] No.45262486{5}[source]
C library is smaller than Node.js (you won’t have HTTP). What C have is much more respectable libraries. If you add libcurl or freetype to your project, it won’t pull the whole jungle with them.
replies(2): >>45263387 #>>45266734 #
66. jmull ◴[] No.45262601[source]
Simply avoiding Javascript won't cut it.

While npm is a huge and easy target, the general problem exists for all package repositories. Hopefully a supply chain attack mitigation strategy can be better than hoping attackers target package repositories you aren't using.

While there's a culture prevalent in Javascript development to ignore the costs of piling abstractions on top of abstractions, you don't have to buy into it. Probably the easiest thing to do is count transitive dependencies.

replies(1): >>45271319 #
67. qudat ◴[] No.45262619[source]
The blast radius is made far worse by npm having the concept of "postinstall" which allows any package the ability to run a command on the host system after it was installed.

This works for deps of deps as well, so anything in your node_modules has access to this hook.

It's a terrible idea and something that ought to be removed or replaced by something much safer.

replies(1): >>45263145 #
68. moi2388 ◴[] No.45262676{4}[source]
Good luck with nr 1 in the js ecosystem and its 30k dependencies 50 branches deep per package
replies(2): >>45264021 #>>45270837 #
69. jmull ◴[] No.45262791{3}[source]
FYI, there's crypto.randomUUID()

That's built in to server side and browser.

70. koakuma-chan ◴[] No.45262797{8}[source]
I think it's justified for Zed. It does a lot of things.
replies(1): >>45264272 #
71. rs999gti ◴[] No.45262851[source]
> supply chain attacks

You all really need to stop using this term when it comes to OSS. Supply chain implies a relationship, none of these companies or developers have a relationship with the creators other than including their packages.

Call it something like "free code attacks" or "hobbyist code attacks."

replies(3): >>45262948 #>>45262967 #>>45263155 #
72. pixl97 ◴[] No.45262918{3}[source]
I mean, what does do good if your supply chain is attacked?

This said, less potential vendors supplying packages 'may' reduce exposure, but doesn't remove it.

Either way, not running the bleeding edge packages unless it's a known security fix seems like a good idea.

replies(1): >>45265911 #
73. galaxyLogic ◴[] No.45262925{3}[source]
So maybe the solution would be to sandbox Node.js?

I'm not quite sure what that would mean, but if it solves the problem for browsers, why not for server?

replies(2): >>45263228 #>>45263300 #
74. __alexs ◴[] No.45262948[source]
I know CrowdStrike have a pretty bad reputation but calling them hobbyists is a bit rude.
replies(1): >>45265117 #
75. orbital-decay ◴[] No.45262954{4}[source]
Modern programming languages don't exist in a vacuum, they are tied to the existing codebase and libraries.
replies(2): >>45264151 #>>45267432 #
76. shermantanktop ◴[] No.45262967[source]
“code I picked up off the side of the road”

“code I somehow took a dependency on when copying bits of someone’s package.json file”

“code which showed up in my lock file and I still don’t know how it got there”

replies(1): >>45263069 #
77. tomjen3 ◴[] No.45262968[source]
That, and the ability to push an update without human interaction.
78. orbital-decay ◴[] No.45263069{3}[source]
All of which is true for far too many projects
79. pixl97 ◴[] No.45263129[source]
>and go back to writing vanilla js

Lists of things that won't happen. Companies are filled with node_modules importers these days.

Even worse, now you have to check for security flaws in that JS that's been written by node_modules importers.

That or there could someone could write a standard library for JS?

80. zarzavat ◴[] No.45263145[source]
I agree in principle, but child_process is a thing so I don't think it makes much difference. You are pwned either way if the package can ever execute code.
81. cesarb ◴[] No.45263151{4}[source]
> If an attacker rug-pulls of course there is nothing that can be done about that other than security scanning.

As another subthread mentioned (https://news.ycombinator.com/item?id=45261303), there is something which can be done: auditing of new packages or versions, by a third party, before they're used. Even doing a simple diff between the previous version and the current version before running anything within the package would already help.

82. pixl97 ◴[] No.45263155[source]
A supply chain can have hobbyists, there's no particular definition that says everyone involved must be a professional registered business.
83. simiones ◴[] No.45263174{3}[source]
That's not the problem. There is a cultural (and partly technical) aversion in JavaScript to large libraries - this is where the issue comes from. So, instead of having something like org.apache.commons in Java or Boost in C++ or Posix in C, larger libraries that curate a bunch of utilities missing from the standard library, you get an uncountable number of small standalone libraries.

I would bet that you'll find a third party `leftpad` implementation in org.apache.commons or in Spring or in some other collection of utils in Java. The difference isn't the need for 3rd party software to fix gaps in the standard library - it's the preference for hundreds of small dependencies instead of one or two larger ones.

replies(2): >>45264977 #>>45268119 #
84. pixl97 ◴[] No.45263178{4}[source]
Developers are perfectly fine with writing insecure JS all by themselves.
replies(1): >>45283673 #
85. ◴[] No.45263227{3}[source]
86. simiones ◴[] No.45263228{4}[source]
You can't sandbox the code that is supposed to talk to your DB from your DB.

And even on client side, the sandboxing helps isolate any malicious webpage, even ones that are accidentally malicious, from other webpages and from the rest of your machine.

If malicious actors could get gmail.com to run their malicious JS on the client side through this type of supply-chain attack, they could very very easily steal all of your emails. The browser sandbox doesn't offer any protection from 1st party javascript.

87. chamomeal ◴[] No.45263264{4}[source]
When I was learning JS/node/npm as a total programming newbie, a lot of the advice online was basically “if you write your own version of foobar when foobar is already available as an npm package, you’re stupid for wasting your time”.

I’d never worked in any other ecosystem, and I wish I realized that advice was specific to JS culture

replies(1): >>45263944 #
88. rs999gti ◴[] No.45263276[source]
> What NPM should do if they really give a shit is start requiring 2FA to publish.

How does 2FA prevent malware? Anyone can get a phone number to receive a text or add an authenticator to their phone.

I would argue a subscrption model for 1 EUR/month would be better. The money received could pay for certification of packages and the credit card on file can leverage the security of the payments system.

89. int_19h ◴[] No.45263300{4}[source]
Deno does exactly that.

But in practice, to do useful things server-side you generally need quite a few permissions.

90. simiones ◴[] No.45263376[source]
Most people have addressed the package registry side of NPM.

But NPM has a much, much bigger problem on the client side, that makes many of these mitigations almost moot. And that is that `npm install` will upgrade every single package you depend on to its latest version that matches your declared dependency, and in JS land almost everyone uses lax dependency declarations.

So, an attacker who simply publishes a new patch version of a package they have gained access to will likely poison a good chunk of all of the users of that package in a relatively short amount of time. Even if the projects using this are careful and use `npm ci` instead of `npm install` for their CI builds, it will still easily get developers to download and run the malicious new version.

Most other ecosystems don't have this unsafe-by-default behavior, so deploying a new malicious version of a previously safe package is not such a major risk as it is in NPM.

replies(2): >>45263567 #>>45263619 #
91. int_19h ◴[] No.45263387{6}[source]
What C doesn't have is an agreed-upon standard package manager. Which means that any dependency - including transitive ones! - requires some effort on behalf of the developer to add to the build. And that, in turn, puts pressure on library authors to avoid dependencies other than a few well-established libraries (like libpng or GLib),
92. lucideer ◴[] No.45263419{3}[source]
To clarify (a lot of sibling commenters misinterpreted this too so probably my fault - can't edit my comment now):

I'm not referring to mitigations in public repositories (which you're right, are varied, but that's a separate topic). I'm purely referring to internal mitigations in companies leveraging open-source dependencies in their software products.

These come in many forms, everything from developer education initiatives to hiring commercial SCA vendors, & many other things in between like custom CI automations. Ultimately, while many of these measures are done broadly for all ecosystems when targeting general dependency vulnerabilities (CVEs from accidental bugs), all of the supply-chain-attack motivated initiatives I've seen companies engage in are single-ecosystem. Which seems wasteful.

93. lucideer ◴[] No.45263490{3}[source]
> NPM is special, in that the exposure is so much higher.

NPM is special in the same way as Windows is special when it comes to malware: it's a more lucrative target.

However, the issue here is that - unlike Windows - targetting NPM alone does not incur significantly less overhead than targetting software registries more broadly. The trade-off between focusing purely on NPM & covering a lot of popular languages isn't high, & imo isn't a worthwhile trade-off.

94. spoiler ◴[] No.45263514{4}[source]
Not saying this in defence of Rust or Cargo, but often times those dependencies are just different versions of the same thing. In a project at one of my previous companies, a colleague noticed we had LOADS of `regex` crate versions. Forgot the number but it was well over 100
replies(3): >>45263778 #>>45263895 #>>45269137 #
95. spoiler ◴[] No.45263554[source]
> So many websites just display text and images

Eh... This over-generalises a bit. That can be said of anything really, including native desktop applications.

replies(1): >>45269027 #
96. lucideer ◴[] No.45263567{3}[source]
> in JS land almost everyone uses lax dependency declarations

They do, BUT.

Dependency versioning schemes are much more strictly adhered to within JS land than in other ecosystems. PyPi is a mishmash of PEP 440, SemVer, some packages incorrectly using one in the format of the other, & none of the 3 necessarily adhering to the standard they've chosen. Other ecosystems are even worse.

Also - some ecosystems (PyPi again) are committing far worse offences than lax versioning - versionless dependency declaration. Heavy reliance on requirements.txt without lockfiles where half the time version isn't even specified at all. Astral/Poetry are improving the situation here but things are still bad.

Maven land is full of plugins with automated pom.xml version templating that has effectively the same effect as lax versioning, but without any strict adherence to any kind of standard like semver.

Yes, the situation in JS land isn't great, but there are much worse offenders out there.

replies(2): >>45264065 #>>45264222 #
97. Tadpole9181 ◴[] No.45263619{3}[source]
`npm install` uses a lockfile by default and will not change versions. No, not transitives either. You would have to either manually change `package.json` or call `npm update`.

You'd have to go out of your way to make your project as bad as you're describing.

replies(2): >>45263716 #>>45264258 #
98. WorldMaker ◴[] No.45263639{4}[source]
- I feel that you are unlikely to need Babel in 2025, most things it historically transpiled are Baseline Widely Available now (and most of the things it polyfilled weren't actually Babel's but brought in from other dependencies like core-js, which you probably don't need either in 2025). For the rest of the things it still transpiles (pretty much just JSX) there are cheaper/faster transpilers with fewer external dependencies and runtime dependencies (Typescript, esbuild). It should not be hard to replace Babel in your stack: if you've got a complex webpack solution (say from CRA reasons) consider esbuild or similar.

- Axios and Jest have "native" options now (fetch and node --test). fetch is especially nice because it is the same API in the browser and in Node (and Deno and Bun).

- Redux is self-contained.

- React itself is sort of self-contained, it's the massive ecosystem that makes React the most appealing that starts to drive dependency bloat. I can't speak to Svelte.

replies(2): >>45271031 #>>45274150 #
99. simiones ◴[] No.45263714[source]
The solution is not to go back to vanilla JS, it's for people to form a foundation and build a more complete utilities library for JS that doesn't have 1000 different dependencies, and can be trusted. Something like Boost for C++, or Apache Commons for Java.
replies(1): >>45267937 #
100. lucideer ◴[] No.45263716{4}[source]
A lot of people use tools like Dependabot which automates updates to the lockfile.
replies(1): >>45284666 #
101. treyd ◴[] No.45263778{5}[source]
That seems like a failure in workspace management. The most duplicates I've seen was 3, with crates like url or uuid, even in projects with 1000+ distinct deps.
102. ◴[] No.45263895{5}[source]
103. jlarocco ◴[] No.45263944{5}[source]
It's not really bad advice, it just has different implications in Javascript.

In other languages, you'd have a few dependencies on larger libraries providing related functionality, where the Javascript culture is to use a bunch of tiny libraries to give the same functionality.

replies(1): >>45264086 #
104. godshatter ◴[] No.45264021{5}[source]
As an outsider looking in as I don't deal with NPM on a daily basis, the 30k dependencies going 50 branches deep seems to be the real problem here. Code reuse is an admiral goal but this seems absurd. I have no idea if these numbers are correct or exaggerations but from my limited time working with NPM a year or two ago it seems like it's a definite problem.

I'm in the C ecosystem mostly. Is one NPM package the equivalent of one object file? Can NPM packages call internal functions for their dependencies instead of relying so heavily on bringing in so many external ones? I guess it's a problem either way, internal dependencies having bugs vs supply chain attacks like these. Doesn't bringing in so many dependencies lead to a lot of dead code and much larger codebases then necessary?

replies(1): >>45265158 #
105. lenerdenator ◴[] No.45264048[source]
> Traditional JS is actually among the safest environments ever created.

> However, processes and practices around NodeJS and npm are in dire need of a security overhaul. leftpad is a cultural problem that needs to be addressed. To start with, snippets don't need to be on npm.

Traditional JS is the reason we have all of these problems around NodeJS and npm. It's a lot better than it was, but a lot of JS tooling came up in the time when ES5 and older were the standard, and to call those versions of the language lacking is... charitable. There were tons of things that you simply couldn't count on the language or its standard library to do right, so a culture of hacks and bandaids grew up around it. Browser disparities didn't help either.

Then people said, "Well, why don't we all share these hacks and bandaids so that we don't have to constantly reinvent the wheel?", and that's sort of how npm got its start. And of course, it was the freewheeling days of the late 00s/early 10s, when you were supposed to "move fast and break things" as a developer, so you didn't have time to really check if any of this was secure or made any sense. The business side wanted the feature and they wanted it now.

The ultimate solution would be to stop slapping bandaids and hacks on the JS ecosystem by making a better language but no one's got the resolve to do that.

replies(1): >>45269574 #
106. simiones ◴[] No.45264065{4}[source]
The point is still different. In PyPI, if I put `requests` in my requirements.txt, and I run `pip install -r requirements.txt` every time I do `make build`, I will still only get one version of requests - the latest available the first time I installed it. This severely reduces the attack radius compared to NPM's default, where I would get the latest (patch) version of my dependency every day. And the ecosystem being committed to respecting semver is entirely irrelevant to supply chain security. Malicious actors don't care about semver.

Overall, publishing a new malicious version of a package is a much lesser problem in virtually any ecosystem other than NPM; in NPM, it's almost an automatic remote code execution vulnerability for every NPM dev, and a persistent threat for many NPM packages even without this.

replies(3): >>45264671 #>>45266678 #>>45267852 #
107. lenerdenator ◴[] No.45264086{6}[source]
Sometimes I wonder how many of these tiny libraries are just the result of an attempt to have something ready for a conference talk and no one had the courage to say "Uh, Chris, that already exists, and the world doesn't need your different approach on it."
108. cxr ◴[] No.45264151{5}[source]
Whatever you're trying to say, you aren't.
109. Yeroc ◴[] No.45264222{4}[source]
> Maven land is full of plugins with automated pom.xml version templating that has effectively the same effect as lax versioning, but without any strict adherence to any kind of standard like semver.

Please elaborate on this. I'm a long-time Java developer and have never once seen something akin to what you're describing here. Maven has support for version ranges but in practice it's very rarely used. I can expect a project to build with the exact same dependencies resolved today and in six months or a year from now.

replies(1): >>45266860 #
110. simiones ◴[] No.45264258{4}[source]
No, this is just wrong. It might indeed use package-lock.json if it matches your node_modules (so that running `npm install` multiple times won't download new versions). But if you're cloning a repo off of GitHub and running npm install for the first time (which a CI setup might do), it will take the latest deps from package.json and update the package-lock.json - at least this is what I've found many responses online claim. The docs for `npm ci` also suggest that it behaves differently from `npm install` in this exact respect:

> In short, the main differences between using npm install and npm ci are:

> The project must have an existing package-lock.json or npm-shrinkwrap.json.

> If dependencies in the package lock do not match those in package.json, npm ci will exit with an error, instead of updating the package lock.

replies(3): >>45264422 #>>45267351 #>>45284723 #
111. rudedogg ◴[] No.45264272{9}[source]
Zed isn’t special, I doubt Sublime Text has thousands of dependencies. It’s a language/culture problem.

Edit: Ghostty is a good counter-example that is open source. https://github.com/ghostty-org/ghostty/tree/main/pkg

replies(1): >>45266706 #
112. Rockslide ◴[] No.45264422{5}[source]
Well but the docs you cited don't match what you stated. You can delete node_modules and reinstall, it will never update the package-lock.json, you will always end up with the exact same versions as before. The package-lock updating happens when you change version numbers in the package.json file, but that is very much expected! So no, running npm install will not pull in new versions randomly.
replies(1): >>45266848 #
113. lupusreal ◴[] No.45264429{3}[source]
> You can't expect people to re-write everything over and over.

Call me crazy but I think agentic coding tools may soon make it practical for people to not be bogged down by the tedium of implementing the same basic crap over and over again, without having to resort to third party dependencies.

I have a little pavucontrol replacement I'm walking Claude Code through. It wanted to use pulsectl but, to see what it could do, I told it no. Write your own bindings to libpulse instead. A few minutes later it had that working. It can definitely write crap like leftpad.

114. debazel ◴[] No.45264671{5}[source]
> This severely reduces the attack radius compared to NPM's default, where I would get the latest (patch) version of my dependency every day.

By default npm will create a lock file and give you the exact same version every time unless you manually initiate an upgrade. Additionally you could even remove the package-lock.json and do a new npm install and it still wouldn't upgrade the package if it already exists in your node_modules directory.

Only time this would be true is if you manually bump the version to something that is incompatible, or remove both the package-lock.json and your node_modules folder.

replies(1): >>45271428 #
115. bakkoting ◴[] No.45264888{4}[source]
It doesn't require 2FA in general, but it does for people with publish rights for popular packages, which covers most or all of the recent security incidents.

https://github.blog/changelog/2022-11-01-high-impact-package...

116. knert ◴[] No.45264977{4}[source]
1000% agree. Javascript is weak in this regard if you compare it to major programming languages. It just adds unnecessary security risks not having a language with built in imports for common things like making API calls out or parsing JSON, for example.
replies(1): >>45268156 #
117. Klonoar ◴[] No.45265047{4}[source]
Your typical Rust project does not have over 1000 dependencies.

Zed is not a typical Rust project; it's a full fledged editor that includes a significant array of features and its own homegrown UI framework.

replies(2): >>45267992 #>>45273067 #
118. kibwen ◴[] No.45265052{3}[source]
> Go modules go even further and add automatic checksum verification per default

Cargo lockfiles contain checksums and Cargo has used these for automatic verification since time immemorial, well before Go implemented their current packaging system. In addition, Go doesn't enforce the use of go.sum files, it's just an optional recommendation: https://go.dev/wiki/Modules#should-i-commit-my-gosum-file-as... I'm not aware of any mechanism which would place Go's packaging system at the forefront of mitigation implementations as suggested here.

119. kibwen ◴[] No.45265093{3}[source]
> PyPI has been ahead of the curve on implementing mitigations

Indeed, crates.io implemented PyPI's trusted publishing and explicitly called out PyPI as their inspiration: https://blog.rust-lang.org/2025/07/11/crates-io-development-...

120. cobbal ◴[] No.45265117{3}[source]
I'm sure no offense was intended to hobbyists, but it was indeed rude
121. marcosdumay ◴[] No.45265158{6}[source]
> Is one NPM package the equivalent of one object file?

No. The closest thing to a package (on almost every language) is an entire library.

> Can NPM packages call internal functions for their dependencies instead of relying so heavily on bringing in so many external ones?

Yes, they can. They just don't do it.

> Doesn't bringing in so many dependencies lead to a lot of dead code and much larger codebases then necessary?

There aren't many unecessary dependencies, because the number of direct dependencies on each package is reasonable (on the order of 10). And you don't get a lot of unecessary code because the point of tiny libraries is to only import what you need.

Dead code is not the problem, instead the JS mentality evolved that way to minimize dead code. The problem is that dead code is actually not that much of an issue, but dependency management is.

122. spankalee ◴[] No.45265911{4}[source]
The supply chain infrastructure needs to stop being naive and allowing for insecure publishing.

- npm should require 2FA disallow tokens for publishing. This is an option, but it should be a requirement.

- npm should require using a trusted publisher and provenance for package with over 100k downloads a week and their dependencies.

- Github should require a 2FA step for automated publishing

- npm should add a cool down period where if won't install brand new packages without a flag

- npm should stop running postinstall scripts.

- npm should have an option to not install packages without provenance.

replies(1): >>45268709 #
123. Hackbraten ◴[] No.45266043{3}[source]
How are users supposed to build and maintain a trust store?

In a hypothetical scenario where npm supports signed packages, let's say the user is in the middle of installing the latest signed left-pad. Suddenly, npm prints a warning that says the identity used to sign the package is not in the user's local database of trusted identities.

What exactly is the user supposed to do in response to this warning?

replies(1): >>45270106 #
124. mhitza ◴[] No.45266658{3}[source]
15+ years ago used to copy paste utility functions from stackoverflow, now people npm installing packages for a function or two.
125. lucideer ◴[] No.45266678{5}[source]
> every time I do `make build`

I'm going to assume this is you running this locally to generate releases, presumably for personal projects?

If you're building your projects in CI you're not pulling in the same version without a lockfile in place.

126. koakuma-chan ◴[] No.45266706{10}[source]
Zed is closer to IntelliJ or VSCode than to Sublime Text.
replies(1): >>45270137 #
127. koakuma-chan ◴[] No.45266734{6}[source]
You can add curl to a Rust project too.
replies(1): >>45270294 #
128. AlienRobot ◴[] No.45266847{3}[source]
I think the sandbox they're talking about is the browser, not the server (which runs node).
129. 0cf8612b2e1e ◴[] No.45266848{6}[source]
The internet disagrees. NPM will gladly ignore and update lock files. There may exist a way to actually respect lock files, but the default mode of operation does not work as you would naively expect.

- NPM Install without modifying the package-lock.json https://www.mikestreety.co.uk/blog/npm-install-without-modif...

- Why does "npm install" rewrite package-lock.json? https://stackoverflow.com/questions/45022048/why-does-npm-in...

- npm - How to actually use package-lock.json for installing based on locked versions? https://stackoverflow.com/questions/47480617/npm-how-to-actu...

replies(2): >>45268083 #>>45284785 #
130. lucideer ◴[] No.45266860{5}[source]
I'm not a Java (nor Kotlin) developer - I've only done a little Java project maintenance & even less Kotlin - I've mainly come at this as a tooling developer for dependency management & vulnerability remediation. But I have seen a LOT of varied maven-managed repos in that line of work (100s) and the approaches are wide - varied.

I know this is possible with custom plugins but I've mainly just seen it using maven wrapper & user properties.

replies(1): >>45267584 #
131. jacques_chester ◴[] No.45266913[source]
Most of the biggest repositories already cooperate through the OpenSSF[0]. Last time I was involved in it, there were representatives from npm, PyPI, Maven Central, Crates and RubyGems. There's also been funding through OpenSSF's Alpha-Omega program for a bunch of work across multiple ecosystems[1], including repos.

[0] https://github.com/ossf/wg-securing-software-repos

[1] https://alpha-omega.dev/grants/grantrecipients/

132. kubafu ◴[] No.45267210[source]
Took that route myself and I don't regret it. Now I can at least entirely avoid Node.js ecosystem.
133. typpilol ◴[] No.45267351{5}[source]
That's not true. Ci will never take new versions from your lock file.
134. kelnos ◴[] No.45267432{5}[source]
Sort of, but I don't really buy this argument. Someone could go and write the "missing JS stdlib" library that has no dependencies of its own. They could adopt release policies that reduce the risk of successful supply chain attacks. Other people could depend on it and not suffer deep dependency trees.

JS library authors in general could decide to write their own (or carefully copy-paste from libraries) utility functions for things rather than depend on a huge mess of packages. This isn't always a great path; obviously reinventing the wheel can come with its own problems.

So yes, I'd agree that the ecosystem encourages JS/TS developers to make use of the existing set of libraries and packages with deep dependency trees, but no one is holding a gun to anyone's head. There are other ways to do it.

135. tetha ◴[] No.45267459{3}[source]
But if we think about a release publishing chain like a BSD process separation, why do they have to be?

Sure, there will be a step/stage that will require access to NPM publish credentials to publish to NPM. But why does this stage need to execute any code except a very small footprint of vetted code? It should just pickup a packaged, signed binary and move it to NPM.

The compilation/packaging step on the other hand doesn't need publishing rights to NPM. Ideally, it should only get a filesystem with the sources, dependencies and a few shared libraries and /sys or /proc dependencies it may need to function. Why does some dependency downloading need access to your entire filesystem? Maybe it needs some allowed secrets, but eh.

It's certainly a lot of change into existing pipelines and ideas, and it's certainly possible to poke holes into there if you want things to be easy. But it'd raise the bar quite a bit.

136. zelphirkalt ◴[] No.45267488[source]
At least in the JS world there are more people (often also more inexperienced people) who will add a dependency willy-nilly. This is due to many people starting out with JS these days.
137. Yeroc ◴[] No.45267584{6}[source]
There are things that are potentially possible such as templating pom.xml build files or adjusting dependencies based on user properties (this that what you're suggesting?), but what you're describing is definitely not normal, or best practice in the ecosystem and shouldn't be presented as if it's normal practice.
replies(1): >>45268891 #
138. zahlman ◴[] No.45267852{5}[source]
Generally you have the right of it, but a word of caution for Pythonistas:

> The point is still different. In PyPI, if I put `requests` in my requirements.txt, and I run `pip install -r requirements.txt` every time I do `make build`, I will still only get one version of requests - the latest available the first time I installed it.

Only because your `make build` is a custom process that doesn't use build isolation and relies on manually invoking pip in an existing environment.

Ecosystem standard build tools (including pip itself, using `pip wheel` — which really isn't meant for distribution, but some people seem to use it anyway) default to setting up a new virtual environment to build your code (and also for each transitive dependency that requires building — to make sure that your dependencies' build tools aren't mutually incompatible, or broken by other things in the envrionment). They will read `requests` from `[project.dependencies]` in your pyproject.toml file and dump the latest version in that new environment, unless you use tool-specific configuration (or of course a better specification in pyproject.toml) to prevent that. And if your dependencies were only available as sdists, the build tool would even automatically, recursively attempt to build those, potentially running arbitrary code from the package in the process.

139. zahlman ◴[] No.45267937{3}[source]
> Something like Boost for C++, or Apache Commons for Java.

Honestly I wish Python worked this way too. The reason people use Requests so much is because urllib is so painful. Changes to a first-party standard library have to be very conservative, which ends up leaving stuff in place that nobody wants to use any more because they have higher standards now. It'd be better to keep the standard library to a minimum needed more or less just to make the REPL work, and have all of that be "builtin" the way that `sys` is; then have the rest available from the developers (including a default "full-fat" distribution), but in a few separately-obtainable pieces and independently versioned from the interpreter.

And possibly maintained by a third party like Boost, yeah. I don't know how important that is or isn't.

140. worik ◴[] No.45267992{5}[source]
What is a "typical Rust project", I wonder?
replies(1): >>45268783 #
141. Rockslide ◴[] No.45268083{7}[source]
Those stackoverflow posts are ancient and many major npm releases old, so in other words: irrelevant. That blog post is somewhat up to date but also very vague about the circumstances which would update the lockfile. Which certainly isn't that npm install updates dependencies to newer versions within the semver range, because it absolutely does not.
142. anon7000 ◴[] No.45268119{4}[source]
Lodash is a good counterpoint, but it’s falling out of style since the JS runtimes support more basic things now.

JS apps, despite the HN narrative, have a much stronger incentive to reduce bundle/“executable” size compared to most other software, because the expectation is for your web app to “download” nearly instantly for every new user. (Compare to nearly any other type of software, client or server, where that’s not an expectation.)

JS comes with exactly zero tools out of the box to make that happen. You have to go out of your way to find a modern toolchain that will properly strip out dead code and create optimized scripts that are as small as possible.

This means the “massive JS library which includes everything” also depends on having a strong toolchain for compiling code. And while may professional web projects have that, the basic script tag approach is still the default and easiest way to get started… and pulling in a massive std library through that is just a bad idea.

This baseline — the web just simply having different requirements around runtime execution — is part of where the culture comes from.

And because the web browser traditionally didn’t include enough of a standard library for making apps, there’s a strong culture of making libraries and frameworks to solve that. Compare to native apps, where there’s always an official sdk or similar for building apps, and libraries like boost are more about specific “lower level” language features (algorithms, concurrency, data structures, etc) and less about building different types of software like full-blown interactive applications and backend services.

There are attempts to solve this (Deno is probably the best example), but buy-in at a professional level requires a huge commitment to migrate and change things, so there’s a lot of momentum working against projects like that.

143. anon7000 ◴[] No.45268156{5}[source]
It does have functions for that, “fetch” and “JSON.parse,” available in most JS runtimes.
144. ZYbCRq22HbJ2y7 ◴[] No.45268405[source]
> These attacks may just be the final push I needed to take server rendering (without js) more seriously

Have fun, seems like a misguided reason to do that though.

A. A package hosted somewhere using a language was compromised!

B. I am not going to program in the language anymore!

I don't see how B follows A.

145. raxxorraxor ◴[] No.45268709{5}[source]
The reality is that for a huge crowd of developers 2FA doesn't do shit.
146. cesarb ◴[] No.45268783{6}[source]
One famous example is ripgrep (https://github.com/BurntSushi/ripgrep). Its Cargo.lock (which contains all direct and indirect dependencies) lists 65 dependencies (it has 66 entries, but one of them is for itself).
replies(2): >>45269118 #>>45277060 #
147. lucideer ◴[] No.45268891{7}[source]
Attackers don't need these practices to be normal, they just need them to be common enough (significant minority of)
replies(1): >>45271145 #
148. olejorgenb ◴[] No.45268926{3}[source]
> The malware includes a self-propagation mechanism through the NpmModule.updatePackage function. This function queries the NPM registry API to fetch up to 20 packages owned by the maintainer, then force-publishes patches to these packages.
149. achierius ◴[] No.45269027{3}[source]
Is that true? The things people use native desktop applications for nowadays tend to be exactly those which aren't just neat content displays. Spreadsheets, terminals, text-editors, CAD software, compilers, video games, photo-editing software. The only things I can think of that I use as just text/image displays are the file-explorer and image/media-viewer apps, of which there are really only a handful on any given OS.
replies(1): >>45269679 #
150. EMM_386 ◴[] No.45269073[source]
> The HTMX folks convinced me that I can get REALLY far without any JavaScript

HTMX is JavaScript.

Unless you meant your own JavaScript.

replies(1): >>45271343 #
151. burntsushi ◴[] No.45269118{7}[source]
Also, that lock file includes development dependencies and dependencies for opt-in features like PCRE2. A normal `cargo build` will use quite a bit fewer than 65 dependencies.

I would actually say ripgrep is not especially typical here. I put a lot of energy into keeping my dependency tree slim. Many Rust applications have hundreds of dependencies.

We aren't quite at thousands of dependencies yet though.

replies(1): >>45277112 #
152. burntsushi ◴[] No.45269137{5}[source]
That doesn't make sense. The most it could be is 3: regex 0.1.x, regex 0.2.y and regex 1.a.b. You can't have more because Cargo unifies on semver compatible versions and regex only has 3 semver incompatible releases. Plus, regex 1.0 has been out for eons. Pretty much everyone has moved off of 0.1 and 0.2.
replies(1): >>45274201 #
153. com2kid ◴[] No.45269574{3}[source]
Python is the other extreme, with an incredibly heavy weight standard library with a built in function to do just about anything.

E.g. there is a built in function that takes elements pairwise from a list! That level of minutia being included feels nuts having come from other languages.

154. spoiler ◴[] No.45269679{4}[source]
You could argue that spreadsheets and terminals are just text with extra features! I'm joking though, but web apps usually are more than just text and images too.
155. biggusdickus69 ◴[] No.45270106{4}[source]
This is a solved problem. https://en.wikipedia.org/wiki/Web_of_trust
replies(1): >>45279432 #
156. biggusdickus69 ◴[] No.45270137{11}[source]
In the amount of bloat, yes.
replies(1): >>45277037 #
157. aakkaakk ◴[] No.45270294{7}[source]
But why, when reqwest is enough for 99% of cases.
replies(3): >>45270603 #>>45278194 #>>45281451 #
158. koakuma-chan ◴[] No.45270603{8}[source]
It's bloated.
159. znort_ ◴[] No.45270695{5}[source]
agreed, bad wording. it so happens though that sw development includes many problems and practices that aren't easy and are still part of the job.
160. znort_ ◴[] No.45270837{5}[source]
there are indeed monster packages but you should ask yourself if you need them at all, because if you really do there is no way around performing nr1. you get the code, you own it. you propagate malware by negligence, you're finished as a sw engineer. simple as that.

personally i keep dependencies at a minimum and are very picky with them, partly because of nr1, but as a general principle. of course if people happily suck in entire trees without supervision just to print ansi colors on the terminal or, as in this case, use fancy aliases for colors then bad things are bound to happen. (tbf tinycolor has one single devDependency, shim-deno-test, which only requires typescript. that should be manageable)

i'll grant you that the js ecosystem is special, partly because the business has traditionally reinforced the notion of it being accessory, superficial and not "serious" development. well, that's just naivety, it is as critical a component as any other. ideally you should even have a security department vetting the dependencies for you.

161. worik ◴[] No.45270888[source]
The Rust folks are in denial about this
162. johnny22 ◴[] No.45271031{5}[source]
Last i checked react's new compiler still depends on babel! :(
replies(1): >>45278070 #
163. Yeroc ◴[] No.45271145{8}[source]
You're talking about things that aren't in the significant minority here.
164. yawaramin ◴[] No.45271279{3}[source]
npm offers 2FA but it doesn't really advertise that it has a phishing-resistant 2FA (security keys, aka passkeys, aka WebAuthn) available and just happily lets you go ahead and use a very phishable OTP if you want. I place much of the blame for publishers getting phished on npm.
165. yawaramin ◴[] No.45271294[source]
Except that htmx's recommended usage is as a single <script> injected directly into your HTML page, not as an npm dependency. So unless you are an htmx contributor you are not going to be installing the dev dependencies.
166. yawaramin ◴[] No.45271319[source]
> Simply avoiding Javascript won't cut it.

But it will cut a large portion of it.

167. yawaramin ◴[] No.45271343[source]
When we say 'htmx allows us to avoid JavaScript', we mean two things: (1) we typically don't need to rely on the npm ecosystem, because we need very few (if any) third-party JavaScript libraries; and (2) htmx and HTML-first allow us to avoid writing a lot of custom JavaScript that we would have otherwise written.
168. k3vinw ◴[] No.45271428{6}[source]
Ahh this might explain the behavior I observed when running npm install from a freshly checked out project where it basically ignored the lock file. If I recall in that situation the solution was to run an npm clean install or npm ci and then it would use the lock file.
169. joquarky ◴[] No.45271822[source]
Some of us are fortunate to have never left vanilla JS.

Of course that limits my job search options, but I can't feel comfortable signing off on any project that includes more dependencies than I can count at a glance.

170. joquarky ◴[] No.45271982{7}[source]
I considered becoming a Zen monk, but then I gave up the desire.
171. deelowe ◴[] No.45272307{3}[source]
It shouldn't matter how many libraries npm supports.
172. wolvesechoes ◴[] No.45273067{5}[source]
> Zed is not a typical Rust project; it's a full fledged editor

Funny that text editor is being presented here as some kind of behemoth, not representative of typical software written in Rust. I guess typical would be 1234th JSON serialization library.

173. junon ◴[] No.45273081[source]
This is going to become an issue for a lot of managers, not just npm. Npm is clearly a very viable target right now, though. They're going to get more and more sophisticated.
174. user34283 ◴[] No.45274064{4}[source]
It's a waste of time to strictly vet dependencies on my side when adding the standard test runner by Meta - jest - alone adds 300 packages to my dependency graph.

So yes, the sprawling deps tree and culture is the problem. We would need to start reducing dependencies of the basic tools first. Otherwise it seems rather pointless to bother app developers with reducing dependencies.

175. user34283 ◴[] No.45274141{4}[source]
Do tell: how many packages are in your dependency graph?

I bet it's hundreds.

Jest alone adds 300 packages.

Consequently I doubt that you in fact "thoroughly and fully" analyzed all your dependencies.

Unless what you're shipping isn't a feature rich app, what you proposed seems entirely unrealistic.

176. user34283 ◴[] No.45274150{5}[source]
Jest alone adds 300 packages by the way.
replies(1): >>45277996 #
177. user34283 ◴[] No.45274187[source]
There is little point in you scrutinizing new dependencies.

Many who claim to fully analyze all dependencies are probably lying. I did not see anyone in the comments sharing their actual dependency count.

Even if you depend only on Jest - Meta's popular test runner - you add 300 packages.

Unless your setup is truly minimalistic, you probably have hundreds of dependencies already, which makes obsessing over some more rather pointless.

178. spoiler ◴[] No.45274201{6}[source]
The reason he went down this rabbit hole was because he was chronically running low on disk space, and his target dir was one of the largest contributors.

Not sure how he actually got the number; this was just a frustrated Slack message like 4 years ago

A sibling comment mentions we could have been using Cargo workspaces wrong... So, maybe?

replies(1): >>45275133 #
179. burntsushi ◴[] No.45275133{7}[source]
He probably just needed to run `cargo clean` occasionally.

But you definitely aren't finding hundreds of versions of `regex` in the same dependency tree.

180. johnisgood ◴[] No.45277037{12}[source]
It is also important to note that this is not specific to Zed. As someone else have mentioned, it is a cultural problem. I picked Zed as an example because that is what I compiled the last time, but it is definitely not limited to Zed. There are many Rust projects that pull in over 1000 dependencies and they do much less than Zed.
replies(1): >>45279323 #
181. johnisgood ◴[] No.45277060{7}[source]
Not quite. He is a better developer than most who happen to minimize dependencies, but according to my experiences it is not as common as you would like to believe. Do I really need to make a list of all the Rust projects I have compiled that pulled in over 1000 dependencies? If I need to do it to convince you, I will do so, as my time allows.
182. johnisgood ◴[] No.45277112{8}[source]
> I would actually say ripgrep is not especially typical here. I put a lot of energy into keeping my dependency tree slim. Many Rust applications have hundreds of dependencies.

Thank you for your honesty, and like you and I said, you put a lot of energy into keeping the dependency tree slim. This is not as common as one would like to believe.

replies(1): >>45277366 #
183. burntsushi ◴[] No.45277366{9}[source]
I agree it's not common. But neither are Rust applications with 1000+ dependencies. I don't think I've ever compiled a Rust project with over 1,000 dependencies.

Hundreds? Yes, absolutely. That's common.

replies(1): >>45277672 #
184. johnisgood ◴[] No.45277672{10}[source]
Maybe I am just unlucky enough to always running into Rust projects that pull in over 1000 dependencies. :D

In retrospect, I should have kept a list of these projects. I probably have not deleted these directories though, so I probably still could make a list of some of these projects.

185. WorldMaker ◴[] No.45277996{6}[source]
Yep, which is part of why it feels real good to delete Jest and switch to `node --test`. I realize for a lot of projects that is easier said than done because Jest isn't just the test harness but the assertions framework (`node:assert/strict` isn't terrible; Chai is still a good low-dependency option for fancier styles of assertions) and mocks/substitutes framework (I'm sure there are options there; I never liked Jest's style of mocks so I don't have a recommendation handy).

(ETA: Also, you may not need much for a mocks library because JS' Proxy meta-object isn't that hard to work with directly.)

186. WorldMaker ◴[] No.45278070{6}[source]
Yeah, I still don't understand a lot of the architecture choices behind the new compiler, including why the new compiler isn't mostly just a set of eslint suggestions with auto-fixes. I've seen the blog posts trying to explain it, but they don't seem to answer my questions. But then I also haven't done enough direct React work recently enough to have need of or actually tried to use the new compiler, so maybe I am just asking the wrong questions.
187. WD-42 ◴[] No.45278194{8}[source]
It requires Tokio, and believe it or not there are actual cases for non-async rust. So you can't use it in that case.
188. koakuma-chan ◴[] No.45279323{13}[source]
Yeah tbh one time I had a Rust job and their back-end had like 700-800 dependencies.
189. Hackbraten ◴[] No.45279432{5}[source]
Imagine a hobbyist developer with a ~ $0 budget trying to publish their first package. How many thousands of km/miles are you expecting them to travel so they can get enough vouches for their package to be useful for even a single person?

Now imagine you're another developer who needs to install a specific NPM package published by someone overseas who has zero vouches by anyone in your web of trust. What exactly are you going to do?

In reality, forcing package publishers to sign packages would achieve absolutely nothing. 99.99 % of package consumers would not even bother to even begin building a web of trust, and just blindly trust any signature.

The remaining 0.01 % who actually try are either going to fail to gain any meaningful access to a WoT, or they're going to learn that most identities of package publishers are completely unreachable via any WoT whatsoever.

190. bigstrat2003 ◴[] No.45281451{8}[source]
Because it requires using async, and for most programs async is not worth the extra effort (plus very heavy dependency in the form of Tokio).
191. yawaramin ◴[] No.45283673{5}[source]
But developers don't typically write malware to deploy on their production systems.
192. Tadpole9181 ◴[] No.45284666{5}[source]
That's unrelated to this.

As well, both Dependabot and Renovate in isolated environments withour secrets or privileges, need to be manually approved, and have minimum publication ages before recommending a package update to prevent basic supply chain attacks or lockfile corruption from a pinned package version being de-published (up to a 3 day window on NPM).

193. Tadpole9181 ◴[] No.45284723{5}[source]
Literally just try it yourself?

The way you describe it working doesn't even pass a basic "common sense" check. Just think about what you're saying: despite having a `package-lock.json`, every developer who works on a project will get every dependency updated every time they clone it and get to work?

The entire point of the lockfile is that installations respect it to keep environments agreed. The only difference with `clean install` is that it removes `node_modules` (no potential cache poisoning) and non-zero exits if there is a conflict between `package.json` and `package-lock.json`.

`install` will only update the lockfile where the lockfile conflicts with the `package.json` to allow you to make changes to that file manually (instead of via `npm` commands).

194. Tadpole9181 ◴[] No.45284785{7}[source]
1. This guy clearly doesn't know how NPM works. Don't use `--no-save` regularly or you'll be intentionally desyncing your lockfile from reality.

2&3. NPM 5 had a bug almost a decade ago. They literally link to it in both of those pages. Here[^1] is a developer repeating how I've said its supposed to work.

It would have taken you less work to just try this in a terminal than search for those "citations".

[^1]: https://github.com/npm/npm/issues/17979#issuecomment-3327012...