Mostly because the vast majority of JS developers don't seem to be aware of the rest of the software universe, and so seem to reinvent the wheel, rediscover the worst of software's history, and discard the most useful of software findings with shocking regularity.
NPM tends to reinforce the worst of the JS world's tendencies.
Primarily, I end up basing this off of the types of libraries being developed for Javascript, and what kinds of articles and thought leaders JS developers tout as innovative.
So by looking at a tiny fraction of the 1 million+ npm libraries, and articles by a few dozen people on the internet, you are able to conclude that the
> vast majority of JS developers don't seem to be aware of the rest of the software universe
Forgive me if I dismiss this as business-as-usual JS bashing
I beg to differ; witness the fibur[0] Ruby Gem. Written by Arron Patterson (@tenderlove) to show that using threads in Ruby is very easy. The Gem consists of this single line:
Fibur = Thread
Of course, he did it as a joke, and it doesn't excuse the serious packages that NPM contains, but it does prove that other languages have single line packages.
I cannot talk for all other languages but at least in Java
1)All packages that are published can never be unpublished or re-released from a different contributor
2)Packages are namespaced
3)Nobody downloads packages directly from the internet. You always use a proxy which in most companies has security scans.
4)There are no "local packages" (like the node_modules dir), so it is impossible for the checked out source code to override your own vetted and secure package.
Not directly related to the incident of the original post, but I was mindblown when I realized that you can unpublish npm packages
1) Same applies for npm (granted, this was only fixed after the left-pad incident, and npm was not the only language's registry to have that issue).
2) As mentioned elsewhere in this thread, npm supports namespaced packages, but they are not mandatory. There are other major languages' registries in same situation.
3) Can you back up 'nobody'. I would suspect a lot of companies don't use a proxy. Some JS teams also use an internal proxy for npm, but it is obviously additional infrastructure to setup/maintain which has a cost.
4) Never heard anyone raise this as a problem before.
> Not directly related to the incident of the original post, but I was mindblown when I realized that you can unpublish npm packages
You can't, with the exception of a 72 hour window, to allow for accidental publishing [1].
1) The fact that an incident actually forced something that Maven registry did since inception, doesn't actually reinfornce the original argument? (that JS developers did not look at what other languages were doing already)
2) Again, whoever thought that namespaces should be optional instead of required "doesn't seem to be aware of the rest of the software universe". Who took this decision? Why?
3) Do a survey on your own. Ask Java developers you know if they use Artifactory/Nexus in their job and note down the percentage. Then ask the same question to JS teams
4) Just because something hasn't been exploited yet, doesn't mean it shouldn't be fixed. By that definition if left-pad hadn't happened would you say that (unpublishing) packages has not been raised as a problem yet?
1) As I said, it was not just JS in this situation at the time, it also applied to other major registries like PyPi. So your point does not reinforce the original attack on JS developers. Congrats to Maven for getting this right.
2) Namespaces were added later. It wasn't "a decision to make them optional". Also check out for the discussion here as to how namespaces don't solve this issue, this point is largely moot.
3) I'm not the person blanket attacking a community. Or making unlikely assertions that "nobody" in the Java world installs direct from the internet.
4) You work for a Linux distribution. You have several global npm modules already installed that are safe and secure. You download source code of a killer app in order to package it. You check the source code itself and it is safe. However you didn't realize that there was a local node_modules directory in the git repo that contains package foo-1.2.3 with replaced code that does bad things. That package overrides your global one. You ship a compromised app.
The above scenario is impossible with maven, because there is no concept of local modules. Only the "global" ones will be used when you package an app. So if you check just the source code and it is safe then everything is fine.
Sounds like your argument boils down to "check the source carefully", not "local modules are evil".
If the source was checked carefully, you'd notice a checked-in node_modules dir.
If you didn't check the source properly, you could install a module that seems like it'ss using a known package, but really is using its own malicious version of the global package.
> Perl (cpan), Python (pip or conda), Ruby (gem), and Rust (cargo) all behave as NPM does
Wrong.
None of them have chosen the "micro-package" way of NPM.
None of them have an average size of "3-10" line of code per package, which NPM has for many MANY packages. Cargo, pip have many packages but "reasonnable size" packages. ( > 100 lines ).
The Micro-package philosophy that NPM chose, meaning every single line of code can have its own package, increase by several factor the number of dependencies required to create anything in JS.
A simple hello world in react already have ~100 dependencies
Nobody is closing their eyes and singing "everything is fine." A large number of small packages is a good thing, and a technically strong ecosystem supports it. Having spent the last week in the internals of glibc chasing bugs in code that has no reason to be jammed into the same library that handles initial program loading, I can attest that there are good, justifiable, technical reasons to do things the NPM way, and I'm glad that there are smart, qualified, talented people implementing that.
I know it's hard for you to imagine, but perhaps the JavaScript ecosystem has some good things about it.
> I know it's hard for you to imagine, but perhaps the JavaScript ecosystem has some good things about it.
There is good in very ecosystem. But a simple keyword "node_modules" on twitter should probably convince you that the good of JS is not in its package system.
To be fair, even the NodeJS author agree on that.
Modularity does not mean "split your code at the atomic level".
Including a package named "one-time", bundled several times in two different versions. To do something highly relevant and technical like "Call a function once".
I have no doubt that it is an Highly complex code that requires indeed two packages..... Irony
Little question: What would have been the probability of purescript getting malicious if its dependency tree would be something reasonnable... Let's say 20 packages instead of the current ~200 ?
The crab-grass like dependencies of many/most NPM packages is scary enough, and then they (or you?), I guess because of lazy loading, to improve responsiveness, update it as you watch.. It's like a scene out of an alien monster movie, where the creature keeps growing more limbs.
conda use namespaces (called channels). If you want a package from a random person, you've to explicitly add it (either globally or when installing the package).
That is why I cited the behaviour and culture of JavaScript-only devs as the primary explanation, with NPM's model reinforcing those issues - issues that do not exist in the same manner in those other languages' ecosystems and cultures.
cargo, at least, does this for the reason Fellshard gives - the Rust team essentially commissioned a copy of Ruby's bundler, without considering whether there was anything to learn from any other language's ecosystem.
Well, okay, if your point of view is that behaving like multiple other major languages and specifically taking the lessons (good and bad) of a specific existing language ecosystem into account before doing your own thing is the same as disregarding other languages and reinventing the wheel, I'm not sure what words mean anymore.
> Well, okay, if your point of view is that behaving like multiple other major languages and specifically taking the lessons (good and bad) of a specific existing language ecosystem into account before doing your own thing is the same as disregarding other languages
If you've only looked at two or three languages that not coincidentally happen to do things pretty much the same as each other, and not looked elsewhere, then you are indeed disregarding other languages.
> and reinventing the wheel
I didn't mention reinventing the wheel.
> I'm not sure what words mean anymore.
Agreed, but i'm not sure i can help you with that.
Cargo is more like npm than Bundler in this regard, as Bundler does not let you have multiple versions of a package at the same time. That lesson was learned from npm, though implemented in a different way.
There's a few different elements of the design space. But, while Cargo can use crates.io, it's distinct from it, so on first principle, this would be a crates.io feature.
That being said, Cargo would also have to understand it, because the Rust language does not understand namespaced external packages, so you'd either have to change the language, or change Cargo to do something to paper over that somehow.
> When we looked at package ecosystems without namespacing, we found that people tended to go with more creative names (like nokogiri instead of “tenderlove’s libxml2”). These creative names tend to be short and memorable, in part because of the lack of any hierarchy. They make it easier to communicate concisely and unambiguously about packages. They create exciting brands.
I will never stop admiring your ability to see the bright side of things.
NPM tends to reinforce the worst of the JS world's tendencies.