These middle deps could pin the exact version, but then when a security vuln is found and a patch issued, these libraries also need to update. This is like a traffic jam. If you're 6 hops from the vulnerable package you need to wait for not one, but six maintainers to push an update to npm before you can clear the security warning.
To get around this, middle packages list semver ranges. And then you have your occasional left-pad issue.
If I had to choose between those two ways to lose, I would use server ranges. The only way to win is to not play at all - have no dependencies.
There you need the way to say "get the new version from 5 minutes ago" without waiting for all levels of the dependency hierachy. Especially as there were a bunch of emergency releases in short sequence and younhabe tonmake sure youbget zhe latest one.
Dependencies are a mess. NIH can't be the solution either, though.
Something like log4j or many packages in the NPM world are so widely used that on any non-trivial project the odds approach certainty that multiple dependencies will specify versions. The more specific the pin, the more likely it is that you'll be unable to ship a security update without risk of a functional change or blocking incompatibility. You can mitigate that with good CI/CD infrastructure and lots of automated testing, but that means taking on more infrastructure expense.
You still have the exact same problem you described with `^2.14.0`. Someone would have to manually update the package to get the security fix in 3.0.0.
Unless you're suggesting code should also automatically update major versions aswell?
If the line between bug and feature were clear. (Log4j worked 100% as specified btw. in regards to log4shell)
Second, log4j is bad examples. Libraries don't pin that at all and people report bug is they do. Libraries are supposed to depend on logging api in general and end project decides whether use log4j or slfj.
We need to get the version that we tested with and know works, which is what it does. When we need to update, we say what version we want.
Java can be a pain, but I'm very glad it doesn't handle dependencies like npm.
I'm still glad that basically noone else handles dependencies like npm.
You can argue that npm's commands are poorly named and guide users towards bad defaults, but saying that it works in a unique way is not true.
Separating the two is handy both due to frequent churn and to avoid transitive dependencies being kept unnecessarily — I’ve seen projects where libfoo stopped depending on libbar a while back but they were still installing it because someone had copy-pasted that block years before and was just incrementing the version.
So that would be “get the one from 5 minutes ago, no questions asked”
You just specify the latest version. But you do it explicitly.
At least with Maven, that's extremely simple. Just add to your project a dependency on that "new version from 5 minutes ago" of log4j. Maven always prefers the version from a direct dependency. You don't have to wait for "all levels of the dependency hierarchy" at all.
In other words.. If there isn't a trusted test pipeline then there's no benefit in delaying the latest version. Might as well just get latest.
Another thing about setting exact dependencies is reducing duplication. Libraries are encouraged to use loose ranges, because if everyone pins exact versions for every dependency, then you could end up with 10 to 20 different copies of 'colors' in your tree, instead of having just 1 or 2 copies that work across the board.