Adding friction to the sharing of code doesn't absolve developers from their decision to blindly trust a ridiculous amount of third-parties.
Adding friction to the sharing of code doesn't absolve developers from their decision to blindly trust a ridiculous amount of third-parties.
Vulnerabilities in Linux distro packages obviously happen. But a single developer cannot push code directly into for example Debian and compromise the world.
This is what happens when nobody pays for anything and nobody feels they have a duty to do good work for free.
Weirdly, some of the worst CVE I can think of were with enterprize software.
If packages had to be cryptographically signed by multiple verified authors from a per-organization whitelist in order to enter distribution, that would cut down on the SPOF issue where compromising a single dev is enough to publish multiple malware-infested packages.
For what it's worth, back when I was active at the ASF we used to vote on releases — you needed at least 3 positive votes from a whitelist of approved voters to publish a release outside the org and there was a cultural expectation of review. (Dunno if things have changed.) It would have been very difficult to duplicate this NPM attack against the upstream ASF release distribution system.
"Large numbers of trustworthy dependency authors in your town can't wait to show you their hottest code paths! Click here for educational livecoding sessions!"
Establishing a false identity well enough to fool a FOSS author or organization is a lot of work. Even crafting a spear phishing email/text campaign doesn't compare to the effort you'd have to put in to fool a developer well enough to get offered publishing privileges.
Of course it's possible, but so are beat-them-with-a-five-dollar-wrench attacks.
How can you guarantee a long trusted developer doesn't have a gun pointed to their head by their authoritarian govt?
In our B2B shop we recently implemented a process where developers cannot add packages from third party sources - only first party like meta, google, spring, etc are allowed. All other boilerplate must be written by developers, and on the rare occasion that a third party dependency is needed it's copied in source form, audited and re-hosted on our internal infrastructure with an internal name.
To justify it to business folks, we presented a simple math where I added the man-hours required to plug the vulnerabilities with the recurring cost of devsecops consultants and found that it's cheaper to reduce development velocity by 20-25%.
Also devsecops should never be offshored due to the scenario I presented in my second statement.
* You are trusting large numbers of trustworthy developers.
* You have established a means of validating their trustworthiness: only trust reputable "first-party" code.
I think what you're doing is a pretty good system. However, there are ways to include work by devs who lack "first-party" bona-fides, such as when they participate in group development where their contributions are consistently audited. Do you exclude packages published by the ASF because some contributions may originate from troublesome jurisdictions?
In any case, it is not necessary to solve the traitorous author problem to address the attack vector right in front of us, which is compromised authors.
If you add jest, the popular test runner by Meta, that's adding 300 packages to your dependency graph.
And here we don't yet have a bundler, linter, code formatter, or even web framework.
So good luck with minimizing those dependencies.
I do not know about NPM. But in Rust this is common practice.
Very hard to avoid. The core of Rust is very thin, to get anything done typically involves dozens of crates, all pulled in at compile time from any old developer implicitly trusted.
Most projects will have a healthy 5-20 dependencies though, with very little nested modules.
At this rate, there's a non-zero chance that one of the transitive dependencies is SQLite itself.
Those numbers are way off their actual number.
That JLR got their factories hacked, rather than customer cars, is less bad for sure. But it's still pretty bad.
Also, before arguing that code generators should get a pass as they don't “end up in the final product”, you really should read “Reflections on trusting trust” by Ken Thompson.
That's bullshit, pure and simple. If you pull in a deeply nested dependency like icu_normalizer it has 30 dependencies, OMGHAXOZRS. I'm doing this, so I don't have to spend a day going through the library.
Except of the 30 depedencies crates, there are 10 from ICUX repository, and then you have almost standard dependencies like proc-macro/syn/quote crates from dtolnay, `zerofrom` from Google. `smallvec` from the Servo project, and yoke from... checks notes... from ICUX.
The only few remaining crates here are `write16`, `utf8_iter` and `utf16_iter` that are written from hsivonen, who is also a ICUX contributor.
So even for 30 dependencies, you actually depend on proc-macro/syn/quote which are foundational crates. Few crates from Google, few crates from Servo, and three crates written by another ICUX contributor.
We started with 30 dependencies and ended up with 3 strangers
But how do we scale that to 1000 dependencies, and every one of their updates? What tools are there to help us, and does the community at large use them?
What I really don't like, and why I wrote that it's a culture issue, is the lightness with which these decisions are often made.
My most popular library has about a dozen dependencies. The README states clearly and “above the fold” what are the core deps (3, no transitive). Every other dependency is either first party, or optional and justified with a comment in the deps file (if you don't use the optional feature, it doesn't end up in your deps file).
There's also a generated BLOB. The generation of the BLOB is reproducible in your own environment, and its provenance attestated.
Those are all risks, that I'm passing on to my users, but I do my best to mitigate them, and communicate this clearly to them.
Use
cargo install cargo-supply-chain
cargo supply-chain --publishers
Run it for whatever you want to check, then have a lunch, it takes 10-30min.It will list exactly how many organizations, and even individuals with publish rights are there. For turso there are 51 repositories, and 243 different individuals with publish rights.
Of course, this still doesn't group by github org and so on.
Isn't it actually the case that you started with 3 strangers, but 27 of them were relatively easy (still took some time) to figure out as safe?
You could of course investigate individuals commits, but that's probably an overkill.
Doesn't this ultimately go all the way up to the top?
You have 2 devs: one who mostly writes their own code, only uses packages that are audited etc; the other uses packages willy nilly. Who do you think will be hired? Who do you think will be able to match the pace of development that management and executives demand?