What Should We Expect From FOSS?
March 18, 2022•2,805 words
Audience
This post is written for an audience of software engineers and assumes general Internet experience. Some definitions are provided below to provide context for those without a background in developing software.
Definitions
- Free and Open Source Software (FOSS): Software with published source code that anyone is free to use, study, or modify
- JavaScript: The world's most popular programming language
- Node Package Manager (NPM): An online collection of JavaScript code and associated set of tools that software developers use to share their work with others
- Package: A bundle of code that can have different versions, allowing for software to be updated over time without forcing code using it to immediately upgrade
- Protestware: A portmanteau of protest and malware, with malware being a portmanteau of malicious software
- Software License: A document associated with a software project explaining how other developers can use, modify, or share the code
Yesterday, a new vulnerability was reported in the National Institute of Standards and Technology's National Vulnerability Database regarding some "protestware" that was added to a popular JavaScript NPM package that gets about 1 million downloads a week.
The owner of the node-ipc package updated the code to add a 1 in 4 chance of deleting the contents of all the files on your computer and replacing them with the ❤️ emoji if you had an IP address that came from Russia or Belarus. This affected versions 10.1.1
to 10.1.3
, meaning a patch version inappropriately delivered this breaking change.
Later, the owner of the package removed this behavior and correctly published a different form of protest as a new major version (11.0.0
) that uses the peacenotwar "protestware" package (which was also written by him). Using node-ipc
will now put an anti-war message in a text file on the user's desktop, instead of modifying existing files on the user's system. This happens for all users, not just those with IP addresses from Russia or Belarus.
While the more malicious ❤️ emoji update was not available for very long, it still effected many projects and people, including popular ones like the Vue CLI, a developer tool to facilitate building websites. One person even claimed to be part of an NGO that lost thousands of files they were collecting to document Russian war crimes.
This whole thing has caused a bit of an uproar in the online developer community. People are flooding the node-ipc
and peacenotwar
repositories with issues calling the developer a Nazi or expressing disappointment because the protestware will damage the reputation and trust of open source software. And even more people are watching the deluge of comments with interest, since this is not the first time a developer has updated a popular NPM package to send a message to the broader software development community.
As a software engineer myself, I fall into that last group of interested spectators. All this has been fascinating to watch and has led me to closely examine my beliefs about what it means to use and develop Free and Open Source Software (FOSS) and how I can prevent something like this most recent NPM issue from affecting my team.
So with that context, let's dive into the actual article: What should we expect from FOSS?
Software Licensing
First, let's start by looking at how software licensing works in the open source community, and whether this particular protestware broke the terms of its license.
The license for node-ipc
is the popular and flexible MIT license, which offers the software "as is", to be used however the user wants. peacenotwar
is licensed under the stricter GPL-3.0 license, which requires any modifications to be published under the same license and the source code be made available.
While I'm not a lawyer, my understanding is that both licences absolve the developer of any liability for issues that arise from using it. This is common in licenses often chosen by open source software, so it's not surprising to see them in this case. But many of the people upset about node-ipc
seem to not understand that downloading software from a random person on the internet comes with no guarantees, especially given the MIT and GPL-3.0 licenses attached.
From my perspective and experience, node-ipc
and peacenotwar
are following the terms of their license, even while providing undesired functionality in an updated version of the node-ipc
package.
What can this tell us about open source software?
To put it harshly: you get what you paid for and this software was free.
Open source is about making sure the source code is easily accessible. It has nothing to do with quality. For every amazing piece of open source software, there are hundreds of awful ones. I should know, since I've written some of the useless ones! All one has to do is look at the GitHub profile of a random developer and you'll stumble across a pile of code that is technically open source, but it is not (and never will be) worth using.
The lesson here is: understand that open source software licenses promise you nothing, other than that their source code will be publicly available for examination.
Versioning
So if there isn't an open source license that protects the user from malicious code updates, what could prevent open source software from delivering malware?
Versioning. Theoretically.
In an ideal world, every update to software would be closely vetted by a team of experts who verified it behaved correctly before being published for the world to use. In that perfect parallel universe, even if a malicious update got past the expert team nobody would download that update before checking it themselves and it would never be set to update to an unchecked version automatically.
Alas, we do not live in such a paradise.
NPM uses Semantic Versioning, which is a widely used standard for labeling new versions of software. But it's just a convention, so there is nothing preventing a developer from breaking the rules when creating new versions. That's what happened with node-ipc
, since it introduced the file-destroying protestware as a "patch" update. Patches are used for non-breaking changes like fixing bugs or make updates that do not break anything for the end user.
Clearly, wiping files on the computer is a breaking change, so the owner of node-ipc
broke the versioning "contract".
Software development relies on an incredible amount of trust. When you use someone else's software, they often have used some other person's software to create it. This leads to a long chain of dependencies, meaning your website to share pictures of cute animals was ultimately created by the work of hundreds or thousands of people. That trust and sharing of quality software is a major part of why there's been incredible growth in the tools available to software engineers and the resulting applications being produced.
But it does have its downside, which was clearly on display with the node-ipc
update.
That trust is exploited by the default behavior of NPM when adding new software dependencies. NPM uses the compatible with version by default when determining dependencies, which will apply new patch versions for packages automatically when running a very common NPM command (npm install
). While this can be helpful for quickly distributing software updates like bug fixes or performance improvements, it should not be the default precisely because people can abuse Semantic Versioning.
Because of the default behavior of a widely used tool, any developers that did not take the extra time to lock their package versions could have woken up a few days ago to a hard drive full of ❤️ emojis.
Engineers should take the time to understand the tools they are using and how software versioning behaviors could impact their code, but the reality is that most don't. Take me for example. I didn't completely understand how versioning worked in NPM earlier in my career even though I had been using it for years and I'm the kind of person who enjoys reading software documentation for fun! Many software engineers face tight deadlines. Unfortunately, things like dependency analysis and reviews don't happen for a good portion of newly written software.
Looking back at node-ipc
's versioning, there is now a version 11.0.1
, which is a new major version that prominently states that the tool now contains the peacenotwar
package, which is far less malicious than the original protestware. This is versioning done properly. While the new version still delivers unwanted functionality, at least node-ipc
is now following versioning standards when making noteworthy changes.
The lesson here is: lock your dependencies and review any software upgrades closely. Open source software does not guarantee that there will be working software or proper versioning. The whole point is to be open and free to everyone and that includes incompetent or malicious actors. You really should vet any new code you did not write yourself before using it.
Is Protestware A Good Way to Protest?
Part of why I wanted to write an article examining this incident and how it relates to expectations in open source is because of the word "protestware". That's a new term I hadn't stumbled across before, and it seems like it's new to most of the wider development community as well.
The situation between Russia and Ukraine is incredibly hard to watch, and I feel deeply for the people of Ukraine who are being unjustly invaded by an autocrat trying to leave his mark on the world. I've got a tinge of fear because I live in Seattle, which could become a target if Putin decides to whip out the nukes. When I saw that a decently popular package on NPM decided to create some havoc for Russian users, I initially chuckled and thought that was a clever way to make a statement. The idea of protestware inherently appeals to me. Especially when used for a cause that I believe is morally just!
I imagined some Russian hacker following Putin's orders to hack a US power plant waking up one day to nothing but ❤️ emojis, ruining his whole day and screwing up his spy work. That's an incredibly satisfying image. I'm having another laugh imagining it just now.
But that's not the reality of the situation.
Internet attacks know no borders. It's entirely possible that some grandma living in Canada got hit because her ISP just bought some IP addresses that used to be located in Russia. Or (if that NGO claim I mentioned earlier is true) some desperate Ukrainian's reporting of a war crime is lost forever because they died from a bomb the next day. Or a Russian anti-war activist loses a valuable spreadsheet containing the contact information for a nationwide network of activists. Or an MIT software engineering student is using a VPN to watch some Russian soccer games and runs the protestware, losing his entire dissertation.
There's so many ways the initial node-ipc
protestware could've hurt innocent people.
Which puts me in an interesting position regarding how I feel about it.
Governments have imposed economic sanctions on Russia. Companies have pulled their business. The global banking system kicked Russia out of SWIFT.
All of those actions hurt innocent people too, but I largely agree with what's being done to dissuade Putin from continuing his invasion. While economic sanctions will hurt Russians who bear no responsibility for what's going on, they are less damaging than a full-on war.
So why can't an individual make a similar choice to attempt to inflict non-physical damage on Russia?
I lean towards supporting the idea of protestware in general, and tolerating this particular situation. The developer screwed up by introducing the file-modifying change as a patch version instead of a major one and not disclosing the change. That broke the social contract for delivering open source software and will damage his credibility going forward. But philosophically he has free-reign to do whatever he wants with the open source software he created, so it's hard to completely condemn him for trying to do his small part in protesting the Russian invasion of Ukraine using the skills he has at hand. It's something that could have caused real damage, though we'll likely never know the true extent. I wouldn't condone this particular functionality change, since I think there are less-damaging ways to get the same message across.
The updated version that leaves an anti-war message on a user's machine is a much easier call for me.
I think it's a brilliant way for a software engineer to make themselves heard. But there is no doubt that it would be incredibly annoying for those using that software. That is, after all, a major point of protests. They don't work if nobody notices!
However, were I using the node-ipc
project I would have lost respect for the developer and the entire project because of the protestware. I get why people are incredibly upset enough to the point of spamming the node-ipc
repository with angry and hateful issues directed towards the developer, even if I think many of the messages go too far and constitutes online harassment. I don't envy him trying to clean it all up and move on from this either.
Overall, I'm going to lean on what seven years of consulting taught me. The answer is: "it depends". There is a proper place for protestware. Software is a form of speech, so I think it should be protected to a reasonable degree, which includes forms of protest. Just as there are bad and good ways to hold an in-person protest, that holds true for doing it in the form of software. That line will no doubt be difficult to walk, as it is for any protest.
What Should We Expect From FOSS?
By this point, I hope I've convinced you that open source software is a grab bag that promises you nothing and everything all at once.
I love software engineering precisely because of open source. I know of nothing like it in human history. Millions of hours have been dedicated to creating software that is given away for free, to be remixed and built upon. That has led to some incredible leaps in digital technology over a few short decades. FOSS, as a concept, is a technological marvel that should be up there in importance next to the discovery of fire and agriculture. It has the potential to radically transform the world. For good, or bad. Just like any powerful technology.
But those lofty expectations should come with a dose of reality. As we saw with node-ipc
, there's danger in blindly accepting open source software from other people before reviewing it yourself. The problem comes from making that a reality. Software engineers use so much software that it would be practically impossible for every developer to understand every dependency change.
It would be great for tools like NPM to make changes that prevent malicious or undesired updates from occurring in the first place. That's something we can push for in the open source community. Software engineers never met a problem that couldn't be solved with more software! 😂
Until we get immaculate tools that save us from ourselves, here are some specific actions that can be taken to secure our projects from being impacted by this kind of protestware in the future:
- Get your software from respectable institutions that have a track record of releasing quality code.
- Lock your dependencies so that you are only ever making a conscious decision to upgrade.
- Review release notes for any new code you are including in your software.
- Contribute to open source software by writing good code or reviewing the code of others to make sure it's working as expected.
- Write your own code where possible. While you don't want to reinvent the wheel, be deliberate about what software you are using.
- Learn about the tools you use and how they work. Don't forget to think about potential attack vectors!
In conclusion, we're probably going to see a lot more protestware in the future as software continues to be an ever larger part of our lives. The node-ipc
issues remind us all that open source software offers no guarantees. While FOSS is amazing, its downsides should be recognized and considered when choosing to use new open source software. Security teams need to become more commonplace in the industry, and better ways of establishing and maintaining trust for FOSS developers and users would make it easier to sleep at night when updating your dependencies.
Ultimately, it's up to software engineers to protect their systems from malicious actors. To do so means understanding where FOSS code comes from and using that knowledge to set realistic expectations for what open source software can do for us.