Always Review Your Dependencies, AGPL Edition
agwa.name
agwa.name
Well... I have reviewed the Go runtime, after I ran into a bug in it... And that's one of the reasons I no longer use Go unless forced to. That thing is ugly under the covers. There is seriously quite a bit of insanity and poor design going on, e.g. when they did the ARM port they had to make a ton of changes to data structures/functions to include the link register, because they didn't or couldn't abstract out architecture specific tidbits like that. Also, the whole C interop stuff is nuts with a ridiculous call chain and several stack switches every time you call to or from C code (this is where I found the bug).
Not saying people shouldn't use it, but I wouldn't hold the deep guts of Go up as an example of stellar development practices. Maybe all the stdlib stuff on top is prettier, but the runtime sure isn't.
Was the code you looked at in Go 1.5 and above? Is it cleaner in 1.4? They used automated tools to convert the C code into Go for 1.5.
https://github.com/golang/go/issues/20058
The recommended fix is to use a library like this one. However, that means your containers blow up with complicated dependency trees so it's not really a good solution for a distributed container architecture (eg Kubernetes).
I love working with Go because of its simple binaries and small containers, but there are some things that it just does not do well.
math/big.addMulVVW
There was some work on it recently.
https://go-review.googlesource.com/q/addMulVVW
But I feel like this issue might have been ignored.
https://go-review.googlesource.com/c/go/+/164966
It might be addressed in Go 1.14 (although it's been marked as Backlog since I last looked at that issue).
https://github.com/golang/go/issues/32492
Point being Go, like OP of this thread suggests, has some issues. This is, to me, a critical flaw preventing my teams from using Go as a primary web language. It is both consistently faster and consistently timed to make an external call to, say, gpg2 to generate a key than it is to use the opengpg lib that relies on math/big. That's nuts.
I am wondering if I am missing something obvious here and would value any opinion.
https://medium.com/code-adventures/farewell-node-js-4ba9e7f3...
PS: I came to statically typed languages as an adult, I actually disliked those languages before I had the lightbulb moment, so I think I might even be more qualified than everyone who hasn't managed to enjoy both sides ;-)
- pip for Python,
- NPM,
- Nuget
- and Maven (and Ant)
Maven is by far my favorite, despite XML.
In fact, give how small pom files are and how little you have to deal with them (if you know what you are doing) I find it amazing how many comments I have had to read about "XML-hell" etc.
Times are changing, so all the power to you if you actually review it. Otherwise the advantage will remain a potential, never to be realised.
I was explaining why to a friend, and it appears that no-one takes this threat seriously, not even in secure/financial apps.
Like you, I wonder if I'm missing something obvious. Why does the npm dependency trust nightmare give me the screaming heeby-jeebies but everyone else thinks it's all perfectly fine?
People who don't worry about it tell themselves that nothing that matters very much is coded in javascript, obvious exceptions notwithstanding.
Maybe the only practical way left to avoid it is to avoid javascript for things that matter, and to avoid products constructed with javascript for uses that matter. This might be an unpopular observation, but that does not make it wrong.
It is possible that WASM can fix much of this, at the cost of exposing ourselves to what might be extreme risks inherent in WASM itself. And of course, to whatever dependencies are brought in for the language we compile to WASM.
I think that's the right balance. clap 3 is and should be treated as a totally different package from clap 2.
Nonetheless I have run into the diamond dependency problem in practice. Their solution is unprincipled and there's no way to turn off the default behavior.
I agree! But it shouldn't fail at compile time with a vexing error message. It should fail to resolve dependencies when calculating a build plan.
I agree that the error message sucks, for what it's worth.
The second biggest flaw is that it couples package management to a programming language, despite those being almost completely unrelated concerns.
Yes it's frustrating. I wish it was more decoupled, maybe with package standards like Haskell tried to do with Cabal.
It makes it hard to use Rust as a drop-in replacement for C. I can add a few C files to a Haskell project without much problem, but most rust code goes via cargo.
We're a long way from it being that simple. There are "hello world" examples, but nothing close to a working GUI in Go-WASM yet.
I'd love a clone of Vue in Go-WASM. Just saying, if anyone out there wants to give it a try ;)
But the repetition in "heebie-jeebies" looks more appealing. Even if grammatically unlikely.
I'm confused now.
Is "heebie-jeebies" intrinsically plural (like "sheep"), and therefore the pluralisation doesn't matter?
Is there even such a thing as a single "heeby-jeeby"?
Heebie-jeebies are best thought of as an affliction, like hives or bedbugs, characterized by shuddering and head-ducking.
My guess is it started as a euphemism for hebephrenia, an obsolete affliction associated with youthful anxiety.
No saying whether that is really where the New Evil Empire got its name.
They play lip service to it being secure, and/or license compliant
A got a taste of it yet again this past weekend when I commented here on HN about GPL and AGPL being licenses that corporations often have concerns with.
I think that's pretty standard for our industry, even outside the often comically lazy world of JS.
Here's a comparison of popular bundlers using a visualization tool I found online:
Webpack - https://npm.anvaka.com/#/view/2d/webpack
Parcel - https://npm.anvaka.com/#/view/2d/parcel
Rollup - https://npm.anvaka.com/#/view/2d/rollup
Granted this only covers the initial package for each of these, there are usually a bunch of extra plugins or cli packages that you'll need to work with each of these but I also found the dependency tree of each of the added Rollup plugins to be less than the other 2.
here's rollup-plugin-babel: https://npm.anvaka.com/#/view/2d/rollup-plugin-babel
But it's not satisfactory because I can't unit test my components properly, or minify/obfuscate properly.
I'm looking at browserify to help with that, but that's going to break my whole build system so I need to find the appropriate time to do that.
Or there's Elm... I keep looking at Elm and wondering if that would solve a lot of these problems...
By adopting any semblance of a modern front-end stack, you're going to be pulling in a huge dependency tree. So, your choices are:
A) Don't do modern front-end development. This, despite being very popular with the HN crowd, is a challenging option. Losing the power of popular frameworks makes it difficult to recruit new developers, slows down developer velocity, and can cause tech debt to accrue more quickly.
B) Validate every dependency. For a skilled security reviewer, this may be possible. For an average developer however, reviewing thousands of dependencies is unlikely to be a good use of time. There are some improvements, automated tools that can be run, but the unfortunate reality is that the NPM attack surface is massive and I don't know of any techniques for producing any truly reliable security assessment.
C) Depend only on packages that you trust and trust them to validate their dependencies. Obviously, if this transitive trust breaks down at any layer then a vulnerability is introduced.
In practice, I've only ever seen individuals and companies do C. I think if there was some tooling around B, that would be the best option. I see a lot of room for disruption here - if there was a way to assign trust to a dependency and then a package-manager level construct that would only allow trusted dependencies to be installed, that might work.
I think the ship has sailed on A.
But the whole dependency hell, left-pad and the likes are a real turnoff. So what I'd probably end up with is coding in pure Js without a package manager or "build system". Basically like you did PHP in the 90s. The question is whether I'd end up with anything remotely sane (already assuming it doesn't involve any crypto or similarly complex).
Also Yarn is very handy. (Fast, simple, correct.)
If you need leftPad, maybe just "vendor" it manually.
You're confusing the tool for the language the tool operates on, akin to claiming modern C++ is Visual Studio.
TypeScript otoh is just ES with types. It moves in the completely opposite direction, adding just enough syntax to get a proper type system in place (a pretty good one to boot).
If anything I would expect it’s syntax additions to be adopted as the standard and directly supported by runtimes. Despite static typing not being that useful for interpreters.
Unless runtimes will completely phase out es, focusing on wasm. (But that will take decades, so not really an either or thing)
The ECMAScript standardization is process is invaluable, after all TS builds upon it. But TS provides a saner subset (and adds a very productive type system), without that I wouldn't touch "modern" JS even with a stick.
Quoting the TypeScript website:
> TypeScript is a typed superset of JavaScript that compiles to plain JavaScript.
There is not a single feature from JavaScript that TypeScript removes.
If you want to have 0 dependencies, you will have to write a lot of code to do things that would just be a line or two in most other languages.
So JS community should throw left-pad in the window and declare underscore.js as a library of choice, so every other library will depend on it and that's about it.
My advice is to avoid most of the JS build tools (i.e. grunt, gulp) by using npm scripts (basically shell commands defines in `package.json`) to trigger build actions, or to start smaller, more specialised tools. At least then you will understand how your build works and won't have an extra layer of buggy plugins screwing things up.
Also being conservative and critical of the dependencies you take on is a great idea. Many smaller dependencies are not worth it. Bigger popular libraries like lodash are often a better deal. Unfortunately this micro-module philosophy and "publish random trash to npmjs.com" attitude has created a huge amount of crud packages.
I've had success organising a bigger project into multiple node packages inside the same git repository and using yarn's workspaces feature to tie it altogether. I avoid the complexity of publishing those (private) packages on npmjs.com. yarn's workspaces make it possible for my main app to find its (internal) package dependencies in the same git repo. is certainly possible to do JS development in a more controlled way.
My advice is to avoid most of the JS build tools (i.e. grunt, gulp) by using npm scripts (basically shell commands defines in `package.json`) to trigger build actions, or to start smaller, more specialised tools. At least then you will understand how your build works and won't have an extra layer of buggy plugins screwing things up.
Also being conservative and critical of the dependencies you take on is a great idea. Many smaller dependencies are not worth it. Bigger popular libraries like lodash are often a better deal.
I've had success organising a bigger project into multiple node modules inside the same git repository and using yarn's workspaces feature to tie it altogether. I avoid the complexity of publishing those (private) modules on npmjs.com. yarn's workspaces make it possible for my main app to find its (sub-)module dependencies in the same git repo.
Naturally it should be easy to specify a whitelist of licenses. (Of course then one has to decide whether to trust the package.json-s.)
That said, security review is hard for any ecosystem. Go probably has inherent advantages compared to the JS ecosystem, simply by virtue of being younger, having a real standard library, being more focused (no browser vs nodeJS issues) etc.
PS: there are projects that aim to do collaborative audit/review for Rust ( https://github.com/crev-dev/cargo-crev ) there should be something like that for the JS world. also there's the NPM "report vulnerability" feature.
In the JVM ecosystem, projects are only allowed in the Maven Central repository if they have their license documented in a machine readable fashion there; it's then trivial to check what licenses you're depending on (and there are several plugins available for doing so). I'm amazed other ecosystems don't offer the same.
Since a dependency can generally do anything your application has privileges for, widely depended-on libraries are an attractive target. A cattle approach means more dependencies, and it being easier for new ones to sneak in.
It depends on your context. Sometimes, dependencies are not pets, but weights on your airplane.
There's nothing wrong until something goes wrong an now you're royally screwed. With zillion dependencies you are at a mercy of zillion maintainers, and none of them has any obligation to you. They can break backwards compatibility in patch releases, introduce subtle behavior changes, steer the project in an unexpected direction or abandon it altogether.
In total, I find it hard to deny how productive the NPM ecosystem can be, despite my philosophical objections to the way the community is run. Am I crazy here?
What I feel they are missing is a community process to consolidate things. You don't need three generations of ten incompatible solutions for a given problem - after some iterations, things should consolidate into one or two more or less standardized libs that don't break existing code at every damn point release.
I don't find churning out code admirable, and I also don't think I've seen any true innovation come out of the NPM scene (bar innovation in the browser/JS space itself, which I think isn't a good measure as it's mostly just working around limitations that shouldn't be there in the first place).
People move billions with a node.js application we develop and the company will eventually be liable if the system is compromised through a targeted attack.
On a different note, I think the ecosystem moves too fast, packages and versions are getting deprecated and new ones getting released constantly. I have the feeling that the whole ecosystem is targeted towards building small MVP apps, not relying a long-term business on it. Maybe I am too harsh here, but that is a frustration growing for years now. I am happy to be proven wrong.
Are there other reproducibility concerns I should be worrying about? Are you thinking npm modules with native code or that (this does happen!) actively pull other stuff during build? Most of those do their own pinning but agree the whole thing is messy.
That is a scary point of view. We have forgotten that there is no such thing as a zero-cost abstraction, apparently, and shovelware developers are now employed by enterprises and write enterprise software...
CPUs aren't getting faster. Software is getting slower a LOT faster than hardware is getting faster, these days, and people are still apparently perfectly fine with adding dependency upon dependency upon abstraction upon abstraction and it's adding up extremely quickly.
A good first step to addressing this is to favor a small copy & paste operation over a small dependency. Lots of people will shriek at the idea of this, but I promise you, all the problems with copying and pasting code are nowhere nearly as severe as all the problems with dependencies. Working to avoid problems you don't have results in creating problems that you definitely do have.
... Which also happen keep their own cattle that you're still responsible for.
It's not so bad in languages with solid standard libraries. In Python projects I might have 20 direct deps, ~50 indirect.
In a real JS project I'm building, I have 17 direct, 3829 indirect. The JS standard library is so damned thin that everything pulls in some random version of the kitchen sink.
yarn list | sed -E 's/.*─ //' | sort -u | wc -l # minus 2
In situations like that your job of auditing licenses, updates, sec issues, etc balloons exponentially with each new dependency.Tooling should absolutely be used, but it still doesn't perform the job of working out whether or not you want to upgrade a component, or whether or not you're likely to have suffered a security breach, or how to report on how well audited your dependencies are.
Dependencies are, if they are to be useful at all, all different. Dependencies are suppliers, in the business sense. Having lots of dependencies loaded at runtime is like a modern just-in-time giant supply chain; it lets you take advantage of efficiencies in exchange for being more brittle.
Or they are like BOM items on a circuit board. Part of the original drive to "componentise" software came from people experienced in electronic engineering; you don't have to reinvent the transistor, you just buy them at a cost of a few dollars for a reel of thousands. But experienced designers will still try to:
- choose more-common components wherever possible
- ensure there are multiple sources for a component
- reduce the overall number of BOM lines, which reduces supply risk and inventory cost
The software world would go completely bananas if the cost for dependencies was not exactly zero. Imagine having to license left-pad.
That doesn't make any sense. That analogy works for mostly-identical computers, where if your software won't run on one computer you can just use another mostly-identical computer.
Almost by definition dependencies are not interchangeable. You can't replace a routine to pad strings with a routine that is a web server. Or a matrix multiplier. Even dependencies that do the same overall job almost never have the same API. Heck, even the same dependency often ends up with a different incompatible API over time as versions change.
> There's nothing wrong with having zillions of them; what you need is good tools to manage them in bulk.
Every added dependency is a risk. Each unintentional vulnerability in each dependency increases the number of vulnerabilities that might be exploitable in your system. And that's just the unintentional vulnerabilities.
Practically all systems provide no useful sandboxing between dependencies, so if any one of your transitive dependencies is malicious, then your entire system is malicious.
Every new dependency also brings in potential license issues, per this article. I think it's unacceptable to have a scarefest about the AGPL, GPL, or LGPL; for a vast number of applications those licenses are just fine. The bigger risks are software that has no license at all, which are a legal risk for any project that uses them until governments change international treaties involving copyright (which is not likely any time soon). But it's certainly true that various licenses are not acceptable for certain situations, and every new dependency increases the risks of licensing problems.
Having no dependencies is absurd; it's uneconomic to build everything from scratch. But every time you add a dependency you need to think about the trade-off; it is sometimes wise to not reuse something.
How do you manage reputation and relationships in bulk? There are transactional costs here. Dependencies created by maintainers with impeccable reputations are a much smaller risk than arbitrary dependencies created by arbitrary maintainers.
My biggest issue is with things in the node ecosystem is breakage, especially React libraries. I was following a NetNinja tutorial series on Youtube. I had to use a Firebase-Redux library for a combined React/Redux/Firebase series. There was a security vulnerability with something down the stack only a few months after the tutorial was out. So to use the updated version I had to use the beta version of a Firebase library which broke the tutorial code despite the library change being a point release like 1.4.0-beta2. Either 1.3.0 to 1.4.0 or 1.2.0 to 1.4.0 would be consider a breaking release for this particular dev.
We have a large group of dependencies chained upon each other with maintainers that have different support commitments and styles. React might be the de facto JS system, but it relies on a large system of these 3rd party packages to do deeper functionality which can so easily break things. I already had to peg React itself to an older version to use this tutorial when it was months old.
I realized at this point how much of a pain it would be to maintain this code in my portfolio if I did something with it. Let alone a paid product. I stopped learning React at this point (or at least learning React+Redux+Firebase).
Ruby sorta has this issue too, but it feels the Node ecosystem is much more accelerated. The Rails framework dominates the gem ecosystem so much usually gems break functionality by the version of Rails they support. So gems often will not update or warn of breaking changes based on the Rails version or ActiveRecord which follows Rails versioning. This makes gem dependencies much more manageable.
The node ecosystem does not have a large dominating framework like Rails. Even if you considered React that framework, Facebook breaks it whenever they please. 16.4 which sound like a minor version update break things. While Rails 4.2 was supported for 4 years. jQuery might be years before it breaks support.
Another problem with npm: every package gets its own copy of its dependencies. Not sure if Rust does that.
It does something halfway in between, which is still a security liability.
If you're looking at the NPM ecosystem and saying, "the number of dependencies is problematic because it takes a long time to review them", I agree with you. If you're looking at the Go ecosystem and saying, "there are fewer dependencies, so I don't need to review them", then that's a security antipattern.
The better way to phrase this to your team is that you need to review dependencies, period. The NPM ecosystem isn't problematic because it introduces a new requirement to review dependencies, it's problematic because reviewing dependencies is harder. You can use NPM all you want for security-sensitive code. You just have to spend the extra time to review dependencies, which means bringing in new dependencies will be much slower than in a shallower ecosystem like Go's.
That's the point of OP's article. You can't skip reviewing dependencies in any ecosystem, in part because all of our ecosystems across the board have crap sandboxing and permissions, but also because of license issues and quality issues like the author found. There is no shortcut for that, whether you're using Ruby, Go, Python, whatever. You have to review your dependencies.
The dependencies themselves are generally smaller and more self-contained. Arguably it is easier to review since the side effects and cross-module behaviors are much more pronounced (it's generally deemed a "bad thing" by the community for modules to make unnecessary global actions)
Instead, phrase it as, "well obviously we need to review our dependencies, so why use an ecosystem where that's hard?" Don't phrase it as a security problem, phrase it as a development time and overhead problem.
Or better yet, let your team use NPM as long as they review the dependencies, and if your dependency tree is really a problem, your team will naturally become annoyed by the extra work and will avoid large dependencies on their own without a lot of extra prompting.
The npm model is a shitshow (multiple versions of one dependency). People defend it for obviously self-interested or lazy reasons.
This seems to apply to security in general. Security these days is doing the minimum amount needed to check some boxes that you are now secure. I suspect a lot of this is driven by incentives. There is few negatives to an individual to use bad security over good security, and the costs of good security means less of the 'good stuff' being developed which results in worse reviews and less prestige. And if people are hacked, the blame is primarily placed on the hackers with little danger to the developers and often even less danger to the company (they might have to spend 5% of the budget they saved on PR to repair their image).
I'm not sure how to fix the issue with prioritization of security. My first guess would be by changing the incentives to companies so they bear the liability in identity theft instead of the user (the very concept of identify theft is a trick to blame the end consumer instead of either the business leaking data or the business giving away money without verifying if data is accurate).
In any case you can’t avoid proper auditing and pen-testing. Even if your app code is rock solid, it doesn’t mean your infrastructure is safe. Or even your office building or the data centre serving the code. Or your employees and their credentials.
All it takes is a decision to use mongodb or redis without auth and to expose the ports to the internet, and the most secure runtime in the world won’t save you then.
Or a bit of social engineering so the attacker is making perfectly legit requests in your perfectly secured app.
This sounds like a solvable problem no one has bothered to solve. We need an analogue of diff highlighting for move-around changes, ideally one that decomposes a changeset into the coarsest block partition such that the changes boil down to a permutation of the blocks.
Something similar should be done for merge commits, which at the moment are completely undebuggable.
It makes license scanning a doddle.
As someone working in the field of license compliance (leading an Open Source Program Office) and dealing with the licensing of tens of thousands of OSS dependencies on a daily basis for a large company I can tell you that license scanning / compliance is anything but a doddle. I do a lot of public speaking on this topic for a summary of the issues I recommend you to have a look at https://static.sched.com/hosted_files/ocs19/c7/OSS-Review-To...
Most modern package managers do offer project maintainers a way to declare the license for a project. However I can tell you that often the declared license does not match the licenses detected in the source code. What counts is the license stated in the source code files not what it's in the gemspec, package.json, pom.xml etc.
This is quite common issue especially for older or larger OSS projects where various contributors have added new code over time that may be licensed under an OSS license that is compatible but not the same as the main license of the projects (Think adding BSD-2-Clause in Apache-2.0 project) What happens is that this contributions get accepted but the project maintainers do not to update the declared license.
Not saying declaring a licensing in a .gemspec file is useless but just recommend you to take it as an indicator of the main license of the project - the project may include source code that licensed under a different license.
Lack of clarity around licenses and security vulnerabilities is a big issue within the OSS community especially as lack of clarity reduces engagement — that means fewer users, fewer contributors and a smaller community. Several organizations are working on a open source solution for this community problems see for further details https://clearlydefined.io/about
Full disclosure I am one of the maintainer of OSS Review Toolkit and contributor to ClearlyDefined.io
Github uses the LICENSE file to detect licenses by default IIRC.
But people will trust the license tag, and end up breaching the license.
And then aren't you just recreating the old fashioned Linux distribution? No-one writes webapps to Linux distros any more; they're always based on language-specific, author-submitted, untrusted package managers because waiting for enough trust to build up to include the latest version of unnecessary-wrapper-for-document.getElementById-0.83.2 is considered stifling.
Maybe nixpkgs comes a little close, somewhat trusted and requiring third-party involvement, multiple versions simultaneously, but including new packages quickly enough. (And indeed, nixpkgs acts as distribution that can run on top of your distro or standalone as NixOS.)
Such a platform is already being developed by various organizations, see https://clearlydefined.io/about and it already in use by GitHub. It's still under development and the initial focus is sharing data regarding copyrights, licenses and source code location for OSS packages.
Note that ClearyDefined only scans the code repository of OSS project it does not resolve dependencies for scanned OSS project. This makes sense as not all dependencies of OSS project B are inherited by a project A which included B as a dependency (due to dependency version resolution by the package manager or dependencies only used for testing).
The idea is that you will us an tool to resolve dependencies for the package manager your project uses which then queries the ClearyDefined APIs.
We are building such a tool as an open source project to manage of licensing and security for dependencies named OSS Review Toolkit (https://github.com/heremaps/oss-review-toolkit).
For a overview of the solution we are building see slide 9 in https://static.sched.com/hosted_files/ocs19/c7/OSS-Review-To...
Full disclosure: I am one of the maintainers of OSS Review Toolkit and also a contributor to ClearlyDefined.
Full disclosure: I am one of the maintainers of OSS Review Toolkit.
Licenses cannot be reviewed automatically in a reliable way. Debian developers review the licenses and store them in a machine-parsable file.
I actually played around with turning it into a GitHub action for further usability improvement, although it needs more work: https://github.com/ralexander-phi/license_approval
I came to the absolute same conclusion as the author: focus on platforms where there is a reasonable standard library. That is .NET in my case and Go in his case. These product dependency trees are much (much) cleaner.
I ended up with writing software to analyze the dependency trees licenses for our browser based products
a) a PR would merge a new dependency with an incompatible license to yours
and
b) allow you to filter out projects based on licenses from search results. in general most of us would prefer to avoid being tainted by GPL code and it'd be great to hide it on the site entirely.
Most programmers feel like hobbyists to me, in their YOLO-approach. Your software might ruin someones day, their life or maybe even end up killing people and more people should take that thing seriously. The way your collegue worked should be the norm.
Only in the Software industry. This is however not normal:
* Mechanical Engineering: Hobbyist bridge vs. professional Bridge – which one should you be able to trust more to carry you?
* Electrical Engineering: Hobbyist wall wart vs. professional wall wart – which one should you be able to trust more not to burn your house down?
* Medical Treatment: Hobbyist vs. professional – which one do you trust more with your body?
The list goes on. Professional work isn't about cobbling together something that barely works at the edge of complexity you can just about manage. Professional work is building something reliable, robust that you can guarantuee for at least to a certain degree.
I know that this isn't how Software Development works right now in most places – that was the whole point of my comment. However it is not normal. It is a bit like with early cars: back then a hobbyist could have easily made a safer car than any professional manufacturer with the right amount of commitment, because there were no real safety standards. Try doing that nowadays.
Edit: Good related talk by the legend himself (Ross Anderson): https://media.ccc.de/v/36c3-10924-the_sustainability_of_safe...
"I used the Singleton Pattern!" "Awesome, you learned about global variables!" blank stare
> Hobbyist wall wart vs. professional wall wart – which one should you be able to trust more not to burn your house down?
I will trust a well-known brand with lots at stake, like Apple. But on the other end of the spectrum, I would put more trust in a charger built from ground-up by a hobbyist I from my local Hackerspace than I would in a random charger off Amazon or AliExpress (and in fact, I had two no-name multi-port USB chargers from China fry themselves).
In general, I'll trust a hobbyist that cares about their craft more than someone doing it for money, unless the latter has their own skin in the game (e.g. doing a bad job would cost them real money, I can sue them, the government could put them in jail).
So with civil engineering, medical care and car manufacturing, I will trust the professionals - because there are strong legal incentives stopping them from cutting all possible corners or doing lots of nefarious things (that doesn't stop these industries from trying, though). But software is a completely different story. There's no protection, no incentives to counterbalance the sociopathy that arises when one optimizes profits too strongly. If you look at modern software, it all looks so great at the point of sale. The bad things - vendor lock-in, excessive telemetry, bad security, selling people out to advertisers, leaking the data due to bad security - all those things hurt users post-sale, and companies know that none of this meaningfully affects their profits in any way.
And even looking at the "normal" industries - at their culture - I have the impression that it's not the "for money" part that's responsible for quality, but the counterbalancing incentives; I think all these industries would be just as bad as software if it weren't for the regulation that retards the profit optimization.
Software projects which do risk injury and dead, for example embedded medical, get a lot more engineering and QA.
The latest Boeeing example is more of a regulatory failure, but somwhere someone sat and coded the behaviour that killed multiple hundreds of people.
We as programmers are just as responsible for what our stuff is doing as anybody else. Maybe even more so, because the work of our hands multiplies. If we put in the effort to make something a little easier, safer and faster that people use every day, you impact more lifes than you might know. And the same is true for the other direction.
Why is it, that software glitches are always seen as a god given higher force, that nobody could have prevented? I know managing complexity is hard, but there is proof out there that it can be done if wanted. We could wait till we are forced to do this by law, or (preferebly) develope at least a pinch of ethos for our own work.
Boeing case is indeed good example. They cared about safety of their planes up until they figured out how to make more money by skillfully avoiding having to care. It looks like it blew up in their faces, but I'm not so sure of that - they're more than "too big to fail", they're a strategic company for the US, so the military won't let them fail.
> If we put in the effort to make something a little easier, safer and faster that people use every day, you impact more lifes than you might know.
My point (here and in parallel reply) is, if "being a professional" is defined as being focused on business objectives and bringing in revenue through your work, then putting in that effort, making things easier, safer and faster, are all - by that definition - unprofessional behavior. Sacrificing time and revenue for goals the market doesn't care about.
...
"Even though I love Rust, I am terrified every time I look at the dependency graph of a typical Rust library: I usually see dozens of transitive dependencies written by Internet randos whom I have zero reason to trust."
I have some kind of point to this comment, but I'm trapped in a sudden feeling of professional malaise.
> This is quite a bit of work, but is necessary to avoid falling victim to attacks like _event-stream_.
Reviewing dependencies is important, but I don't think anything the author mentions would have made a difference with event-stream. The whole issue there was that malicious changes were snuck in via a change of maintainers and a later update to a child dependency, so when people initially adopted it as a dependency there were no red flags in the library to find.
The only thing that really prevents such issues is version locking of transitive dependencies (which the author doesn't mention, but it could be that his package manager does it by default, or similar..).
I should add, I was probably wrong to talk about lockfiles preventing such issues. With event-stream the malicious code was hidden deviously enough to evade a pretty rigorous check - if a Node update hadn't deprecated one of the functions used in the payload, I suppose we might still not know about it. In such cases a lockfile is at least a layer of defense, but naturally it only helps if you're lucky enough to have installed the library before it got corrupted..
At least that's my theory. You could test this by inserting an empty <script> tag into the <body>, which should delay DOMContentLoaded until the style arrives and prevent the flash of unstyled content.
Ceterum censeo go inferior est.
Because that dependency might itself have dependencies and this quickly grows out if hand with different versions etc. It might work now, but will it in the future? How many different versions of the same package do I really need to depend on?
Try upgrading typescript to the latest version. I think that's a fair definition of "modernisation" and something which should be benign.
But now all of a sudden you have to upgrade every dependency to the latest version - or write your own .d.ts files - since they're typically written to the current library version - typescript version combination.
The language and standard library is always backwards compatible (minor security fixes excepted). So updating to a newer language version just works.
Major libraries at the roots of many dependency trees have upgraded in backwards incompatible ways a few times, but the community has pretty consistently come together and helped move every other library that anyone uses to the new version.
* Import the dependency manually. This is taking a dependency without the formal description a package manager gives you, making it harder to audit, update etc.
* Write the functionality yourself. This guarantees you are not exposed to malicious code, but it takes time and your solution will likely have more bugs than a widely used solution. You also lose the ability to use other dependencies that build on top (e.g. React components) because you are now outside the mainstream.
What is actually needed is better tooling to analyze and prune dependency graphs.
Cur?
Obviously this doesn't solve the general quality problem with dependencies that the author notes, but it fixes some licensing issues.
Yeah, and I'm not either. I have never decided to vendor dependencies, and my only modifications to GPL code were to upstream (so I didn't have a legal obligation to distribute the modified code - the distributors of the code I modified do). I just think automated license compatibility checking could be a good move for the ecosystem.
Also to be clear, I was talking about npm-like ecosystems. In my mind this includes npm, poetry and cargo (and probably more).
I myself saw a pm2 error message in Linkedin's error 500 output
To be clear: everyone has the free right to license their stuff how they like. I just think NPM as a ecosystem should be opinionated (and it is... Towards MIT. Just not completely).
Maybe there should be an organized effort to make some sort of compatibility matrix for all the OSI licenses...
[1] https://yarnpkg.com/lang/en/docs/cli/licenses/
[2] https://github.com/yarnpkg/rfcs/blob/master/accepted/0000-li...
https://github.com/microsoft/tslib/issues/47
(Disclaimer: I like TS, but I filed the above bug.)
>Please do not use "public domain", it's not a license and it makes it impossible to use such code in corporate context. //
Seems pretty ridiculous, "can't use code unless it's encumbered by licensing restrictions"??
https://creativecommons.org/share-your-work/public-domain/cc... https://creativecommons.org/publicdomain/zero/1.0/
Some works have no copyright, typically because they're the product of a US Federal institution, or the copyright has expired. In American English this copyright-free state is also known as "public domain". (In British English it can mean something quite different.)
To put something in the "public domain", you need to make a statement of such. In other words, a licence. You could just say "I put this in the public domain" but it may not provide the certainty that bigcorps like. CC0 is a way of saying this in bigcorp-friendly language. (The CC0 page at https://creativecommons.org/share-your-work/public-domain/cc... explains this well.)
Alternatively, you can use WTFPL, which is a really great way of putting your works in the public domain while guaranteeing that bigcorps won't use them (see: statements on HN by Google people, passim).
I thought the point of WTFPL was that you didn't care who used your code for what.
https://opensource.google/docs/thirdparty/licenses/#wtfpl-no...
It's more than that - it's impossible to place things in to the public domain in many juristictions - like the UK.
(This is because copyright is property, and property must have an owner under the law of England and Wales [also Scots law I think, but I don't know]. Thus, a declaration that something is in the PD is of no effect.)
Moreover, Google have been allowed to assume ownership of intellectual property (content of books). The moral rights on those properties have been effectively cancelled.
Sure, bona vacantia is A Thing - but your comment spells it out. The copyright gets _sold_ by the state to whoever wants to buy it.
That is not the same thing as public domain - the new owner can enforce their monopoly rights over the works which can screw over anybody depending on the work being "in the public domain".
I'd argue that when I release something to the public domain that means that I give an open license such that the work can be used as if in the public domain until such time as it actually enters the public domain.
But, yes, I can see how that's a risk companies might avoid until caselaw backs that up.
Some communities like the ClojureScript uses it extensively and a front end project in ClojureScript require very few dependencies.
Edit Answering to Jyaif: Anecdote is not data, here is it comparing the popularity of Closure library against Angular -another Google technology-: https://trends.google.com/trends/explore?date=today%205-y&ge...
You must be new to this whole Microsoft vs Netscape thing :-)
What Microsoft should do is get Google & co. onboard with creating a full-featured standard library. Microsoft going at it alone would create a huuuuuge backlash because of ye olden days.
In case it's useful to anyone else, here's an older copy of it: https://gist.github.com/robmccoll/240317eceb73e3f4e29ea662e3...
In the CII Best Practices badge project we use both the "license_finder" program (which is an OSS tool) and the FOSSA service ( https://fossa.com/ ). Both examine the dependencies for licensing issues. While something could still slip through, it's much less likely, and more importantly we have a really good case for showing due diligence. I'm not a lawyer, but I do know that courts look very favorably on people who are demonstrably making an effort to meet their legal obligations. You're way less likely to have legal problems that way.
It will only work if you are vendoring your packages though (and you should!).
If this guy has to work on a "modern" frontend project, he's gonna review dependencies until the heat death of the universe.
Don't let some drive to be "modern" cause you to use libraries that make things more difficult than using vanilla JS.
At our company we use whitesource to scan each and every build for these kind of license violations.
Slightly ridiculous that we're getting to this point :-)
- avoid dependencies where you reasonably can. Less moving parts are usually good
- just have a look at the dependencies of your dependencies - this might help you decide which one to trust
Dependencies are more dangerous (in this sense) because they compile into your application, so they can do anything they like to your customer data. A malicious tool could monitor your keystrokes and phone home, but it won't get installed on your production server.
A further problem with npm dependencies is that they get told when they're operating in dev mode and when in production mode. So malicious code can hide itself during dev and test, and then only do the bad thing on the production server.
On a somewhat related topic: https://drewdevault.com/2019/12/09/Developers-shouldnt-distr...
What is the point of having a license like that? Trolling?
AGPL was intended to close the SaaS gap in copyleft software. Essentially, prior copyleft provisions don't kick in if you never distribute the software itself, so if you only offer network interaction with the software you have no duty to redistribute.
AGPL is intended to restore the freedom of end users to have access to the source of the software they interact with, even if it lives on someone else's computer. As with all copyleft software, it does this by restricting the rights of the developers of the software (to keep their source proprietary).
As always, it is the old philosophical split between MIT/BSD style licenses and GPL style licenses. MIT/BSD provide you with complete freedom, including the freedom to use that library and keep your source closed. GPL is intended to prevent that and to build a common base of software on which further things can be built.
(there is also Lesser GPL license, which only kicks in for modifications to the library itself. So if you write something that uses a LGPL library, you don't have to give away source for the larger program as a whole, just the LGPL program and any modifications you made to it. This is essentially removing the "viral" copyleft provisions.)
A lot of popular packages being used in complete contravention to their license terms, and care not at all their dependency chains pulling quite restrictive licenses.
In many language ecosystems, logging to stdout tends to be the right thing to do in a lib as it does not impose any specific choice of logging implementation.
One always can recapture stdout and route it through one's logging solution of choice; doing something analog with an extraneous logging library can be harder if not unfeasible.
Are things different in Go land?
In Go, I would assume that a library that needs to log would do one or more of the following a) offer the ability to disable logging b) offer overriding the output that it uses for logging probably with an io.Writer interface or something c) accept a log.Logger or offer an interface that something like log.Logger meets. Ideally it would offer an interface that supports some key-value meta data to be able to have nicely structured logs with formatting independent of the library.
The idiomatic solution is to have a standardized facade like SLF4J and then behind the scenes the "end user" (final developer writing the application) can choose their own logging backend to drive the facade.
The slightly less idiomatic way is that everybody does their own thing and then you use bridge libraries to hijack all of the various logging APIs and redirect them through SLF4J or through your logging backend of choice.