I've tried to remove single-line dependencies only to have the PR rejected by the creator of the tiny library who happens to contribute to the parent library.
IMO the Javascript ecosystem really needs a decent standard library to remove the inordinate amount of power granted to these these tiny library squatters who wrote 5 lines of code and a package.json file 10 years ago.
And that was one situation. The mindset of the Javascript ecosystem is still to maximize code reuse, meaning even if the tiny library maintainer isn't a maintainer of the parent library, the parent library still frequently clings to their one-line dependencies when I've tried removing them. Thus granting the tiny library owner tons of power like the maintainer of "colors".
So fork it and throw out everything you don't like.
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.
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.
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.
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.
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.
Our industry has gotten along for far too long with zero liability or accountability.
Not only that, even if you excuse their lack of ethics, there's a basic competence issue: they have a basic failure to learn from history and the most basic part of this, which is that you shouldn't be pulling live from the internet.
Perhaps you have another solution in mind? I think something along the lines of package-level content security policies with granular permissions has a lot of potential.
I did try (2) for awhile with some success. You basically vet everything you import.
This generally follows the same rules of supply chain validation expected _and common_ in other industries where people actually give a crap about what they are doing.
In the case of large projects, especially those with a solid track record of testing and security issue management, the vetting is organizational. You don't need to read every line of Kafka (though you should, as I did, actually look through it to see what you're getting into), as an example, at least today.
But for smaller projects, just like with smaller vendors, you need to go deeper. You do need to read the code. Then you look at their issue tracking and see if they have any concept at all of quality, sanity, security notices, what their maintainer attitude is, and so on. You definitely read the code. If you're sloppy, you at least read through a good sample of the code. Again, diligence - you have the obligation to your downstream to know what you are getting into.
This is no different than the vendor management you expect in pretty much every supply chain that you interact with. Food, cars, medicine, pharmaceuticals, building materials, heavy machinery, embedded software in medical devices, and so on. Software has gotten away with complete negligence for a long time and instead of addressing it, the common practice has gotten worse and worse. At some point, we are going to accidentally kill someone.
Then, on top of that, you lock it down. You mirror it, you pin it, you make an active plan to monitor the project to make sure you are aware if it is abandoned, hijacked, deleted, etc. You take responsibility for dealing with these possibilities. You mitigate immediate threat by not pulling random crap live when you build. You further make sure you partition your system such that code you have not classified as high quality has a reasonable blast radius and security boundaries.
But whatever, let's say you're a typical valley company that operates like a psychopath and you don't care about that. What companies should be worried about is liability. Yes, most of the security activities for most SaaS and other SW is laughable and mostly theater and checklists. But there is liability nonetheless. After all, you are about to represent it as high quality software and you are taking on the liability. No judge in the world is going to let you go with the "but it was this javascript we pulled in, not ours" excuse.
We built quite substantial systems using this approach, and it was important in the domain that we were working in to have done so. It is not without hassle and cost.
Really, what are we talking about here? It's _too expensive_ or _too difficult_ to have even the slightest quality verification of software? The industry is a complete joke if that is true.
Completely agree, which is why I support such endeavors wholeheartedly.
The comments here have convinced me that the industry is basically beyond self help.
Now, who's gonna pay you for writing that single functionality whole year? Sure, you tested, documented, did everything right, you may have almost no bugs, pretty code, decent test coverage, unit tests, integration tests, UI tests, performance tests, edge cases ironed out, top notch performance, UX no-one matches, one click deployment, static code analysis, linters, fuzzers, vulnerability scanner tools, monitoring, auto scaling... while you get there, your startup may be no more. Or maybe just a money sink: https://thedailywtf.com/articles/unseen-effort
Alright, I'm little off the track, but not every software project is comparable to automotive/air/rocket/med/... industry. Ofcourse you will put 10x+ more money/time/effort if human lives may be impacted with your commit.
To put that into context, let's appreciate SQLite - software that is thoroughly tested and your airplane shouldn't be afraid to run those. From the creator of SQLite:
> I’m going to write tests to bring SQLite up to the quality of 100% MCDC, and that took a year of 60 hour weeks. That was hard, hard work. I was putting in 12 hour days every single day. I was just getting so tired of this because with this sort of thing, it’s the old joke of, you get 95% of the functionality with the first 95% of your budget, and the last 5% on the second 95% of your budget. It’s kind of the same thing. It’s pretty easy to get up to 90 or 95% test coverage. Getting that last 5% is really, really hard and it took about a year for me to get there, but once we got to that point, we stopped getting bug reports from Android
https://corecursive.com/066-sqlite-with-richard-hipp/#testin...
;)
What we are missing on the software industry is proper liability.
No, it's your responsibility to make sure your dependency tree is alright.
Your personal definition of 'alright' may be more easily satisfied if the packages you choose to depend on autonomously practice some level of responsibility towards their own dependencies. Choose wisely.
But there is no way to dictate your requirements to dependencies, or impose some kind of responsibility or demand some kind of warranty. You can accept what is offered, or not. In fact, if you are using svgo, even indirectly, you have agreed to this: https://github.com/svg/svgo/blob/main/LICENSE
>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
So svgo doesn't have to care and you can't make them. Even if they do care, there's no guarantee they will meet your standards - and you still can't make them.
If you want someone to blame, find someone willing to sign a contract that says you can blame them.
Efforts within NPM and github to control this situation are simply the bare minimum of case-by-case disaster mitigation, in the interest of reputation alone. If you're using their infrastructure, you apparently find this acceptable.
You're responsible for every dependency you add to your project and that includes all sub-dependencies. Your users will sue you for not doing your due diligence. You may turn around and try to sue your suppliers but that doesn't absolve you of your responsibility.
NOTE: this isn't an open source versus closed source thing. Linux has distributions which test included packages (to varying extents, I'm sure) and some of these are commercial operations. It's not impossible to have code whose verification you have paid for, to one extent or another, even with open source. (and hey, you can install malware with automatically updating closed-source see Solarwinds).
The point here is how we can make it easier for svgo and every other package to avoid the problem in the first place.
For any project using NPM, it was an absolute nightmare. Dependencies 3 or 4 levels deep would get flagged, and there wouldn't be a way to resolve them. The security teams didn't care, and multiple projects were left stranded. Since resolving those issues would mean having to contribute to open source, which we weren't allowed to do.
On the other hand, because we had specific security teams doing the scanning and assessing the results, you weren't allowed to question them, because they could just block your entire project. So developers were extremely unhappy with them, and what ended up happening is that developers just did what the security teams asked, without questioning. Which to me, let to more security concerns, because we were just pulling in libraries without knowing what had changed.
Sadly, the few devs who stopped relying on third party dependencies all left, because most of their work took longer (since they were implementing stuff that third parties usually do). Business teams took notice and questioned why everything was taking longer.
The resolver tool we used couldn’t fix dependencies that deep even when there were fixed versions available. And since their internal processes didn’t use the same audit tooling, Facebook devs would often close issues requesting dependency upgrades to fix those not actually security issues. I think Dan Abramov wrote a post on overreacted about it at some point too. I’m not convinced any of the time we spent on those issues was well spent to be honest.
Obviously a non-issue, but you still had to verify, and document everything. Best practice would be that we ran this scan on every commit, but the scan took about 15-20 minutes. It just ended up being something that was part of our release process, with the obvious danger of breaking our application right before release.
All in all, it stopped me from relying on third party modules, and tried to use as much vanilla code as possible.
By the time you got to the end, it would be time to go back to beginning and start over again...
https://www.reddit.com/r/ProgrammerHumor/comments/6s0wov/hea...
>Heaviest Objects in the Universe:
>Sun
>Neutron star
>Black hole
>node_modules
Looking at one of our production projects, we use colors via: "css-loader" -> "cssnano" -> "svgo" -> "colors"
I wish I could say I spent the hours to go line by line through every dependency of our app. But that wouldnt leave much time for anything else.