Maven Central exists for decades the amount of incidents of people stealing namespaces is minimal.
One can't simply publish a package under the groupId "com.ycombinator" without having some way to verify that they own the domain ycombinator.com. Then, once a package is published, it is 100% immutable, even if it has malicious code in it. Certainly, that library is flagged everywhere as vulnerable.
It baffles me that NPM for so long couldn't replicate the same guardrails as Maven Central.
But in the Maven/Gradle ecosystem, most projects pin exact dependency versions. Support for version ranges and dynamic versions exist, but they are generally avoided because they hurt reproducible builds. That means a malicious new release does not automatically flow into most consumers’ builds just because it was published.
I'd go as far to say that NPM should:
1. Enforce scope (namespace) requirement, and require external verification (reverse DNS for example).
2. Disable version range support out of the box. User must --enable this setting from the command line at all times.
3. Remove support for install scripts completely. If someone wants to publish a ready-to-run software, there are plenty of other mechanisms.
This directly influences how well e.g. version pinning works. In the Java world, package versions are _relatively_ independent from eachother and have few transitive dependencies, and as such version conflicts are relatively rare. This means you can get away with full pinning of all dependencies, with the occasional manual override of a conflicting transitive dependency.
This doesn't work in JavaScript. The dependency ecosystem is massively intertwined, if every library would specify exact versions you'd end up with literally hundreds of conflicts to resolve. That's not feasible. As a result, they've chosen the middle ground of using lock files in addition to version ranges.
This also hurts the effectiveness of verified namespaces: when packages come from hundreds of different sources, you're not going to notice 1 or 2 sketchy ones in there.
Other consequences of the big monolithic packages in Java are that updates tend to be less frequent, and more often from large reputable venders. Both of these help to reduce the problem too.
While the JavaScript toolchain can definitely learn a lot from the Java toolchains, the problems it needs to solve are not the same, and thus solutions don't translate 1-1.
At least I hope that they'll get rid of install scripts, that's such a low hanging fruit that really should've be done a decade ago.
Who the heck says everyone who publishes a library has a domain? That seems absurd.
Attackers go where the victims are. Frontend is a monoculture with the vast majority using NPM; backend, less so. This isn't an excuse for NPM, but another strike against it.
You could also argue that the attacks make a deeper point about frontend vs backend devs, but I won't go there.
And that number tends to reduce even more when the ecosystem matures.
However the current npm vulns used a post install script.
With many other languages, you have a lot of functionality out of the box. Certainly, there have been bugs and security issues, but they're a drop in the bucket compared to what you see in the JS ecosystem. With other languages, you have a much smaller external dependency graph and the core functionality is coming from a trusted 3rd party.
The issue isn’t that the functionality doesn’t exist, it’s always backwards compatibility with versions where it did not yet exist.
I'm not saying that npm is doing everything right, but I suspect that beyond the obvious low-hanging fruit that we hear about pretty consistently with npm there's probably a long tail of less obvious stuff that can be exploited that will not be specific to npm. The fundamental problems with supply-chain vulnerabilities aren't going to go away if npm magically became pip or go modules overnight.
Both the Browser and Node.js standard library are fairly extensive. I don't think there's much you can do with other language you can't do with Node.js. And as a lot of newer languages have demonstrated (like zig and hare), you don't need an extensive one.
NPM's achilles is the pre/postinstall step which can run arbitrary commands and shell scripts without the user having any way to intervene.
Dependencies must be run in isolated chroot sandboxes or better, inside containers. That would be the only way to mitigate this problem, as the filesystem of the operating system must be separated from the filesystem of the development workflow.
On top of that most host based firewalls are per-binary instead of per-cmdline. That leads to the warnings and rules relying on that e.g. "python" or "nodejs" getting network access allowlisted, instead of say "nodejs myworm.js". So firewalls in general are pretty useless against this type of malware.
Your mismatch is that you think in policies, not assessments here. Nothing in my normal go workflow will ask me if I want to run "curl download whatever from the internet" when I run go build.
Though I agree with the difference in workflow, there is not a single mechanism in go catching this. go.mod files can be just patched by the worm, and/or hidden behind a /v123 folder or whatever to play shenanigans on API differences.
Examples that come to mind: webview/webview, webkit, cilium/ebpf and most other CGo projects that I have seen.
Something fascinating about the design and architecture of programming languages and their surrounding ecosystems is the enormous leverage that they provide to the "core team":
For every 1 core language developer[1]...
... there may be 1,000 popular package developers...
... for which there may be 1,000,000 developers writing software...
... for over 1,000,000,000 users.
This means that for every corner that is cut at the top of that pyramid, the harms are massively magnified at the lower tiers. A security vulnerability in a "top one thousand" package like log4j can cause billions of dollars in economic damage, man-centuries of remediation effort, etc.
However, bizarrely, the funding at the top two levels is essentially a pittance! Most such projects are charities, begging for spare change with hat in hand on a street corner. Some of the most used libraries are often volunteer efforts, despite powering global e-commerce! cough-OpenSSL-cough.
The result is that the people most empowered to fix the issues are the least funded to do so.
This is why NPM, Crates.io, etc... flatly refuse to do even the most basic security checks like adding namespaces and verifying the identity of major publishers like Google, Microsoft, and the like.
That's a non-zero amount of effort, and no matter how trivial to implement technically or how cheap to police, it would likely blow their tiny budget of unreliable donations.
The exceptions to this rule are package managers with robust financial backing, such as NuGet, which gets reliable funding from Microsoft and supports their internal (for-profit!) workflows almost as much as it does external "free" users.
"Free and open" is wonderful and all, but you get what you pay for.
[1] Most of us can name them off the top of our heads: Guido van Rossum, Larry Wall, Kerningham & Richie, etc.
In addition, crates.io has not flatly refused to support namespaces, there's an entire accepted RFC for it: https://github.com/rust-lang/rfcs/pull/3243
At the same time, note that namespacing does nothing to prevent any sort of problem here. Namespacing is great for package organization and making provenance more deliberately obvious, but beyond that it's not a security measure.