TLDR: A vessel called Mimemagic run aground, blocking a vital trade route and halting traffic for all others and forcing a reroute for some for six days.
Jokes aside, what happened in Rails last week is unprecedented, at least since I started working with Rails 4. Unless it did happen and I missed it.
As far as I understand, it was an issue with licensing. For some, licensing is not an issue of concern; a few people grab any open-source code available and use it anyhow they want. I was one of these people, but I’ve come to learn to pay more attention to the kind of dependencies I use and the licenses attached to them.
This blog post is a summary of what I think is happening. This post is a compendium of the timeline of events, solutions people have found to circumvent the yanking of
mimemagic and how open-source licenses work.
So, What Happened?
While entirely unrelated, six days ago, a massive cargo ship got stuck in the Suez Canal. The memes with ships is based on this vessel, Ever Given. The reason people couldn’t ship has nothing to do with this ship though.
The maintainer of
shared-mime-info, Bastien Nocera, filed an issue on mimemagic to resolve some licensing inconsistency.
shared-mime-info is a package that contains the core database of common MIME types that
shared-mime-info is under a GNU General Public License (GPL) and mimemagic, prior to version 0.3.7, was incorrectly licensed under MIT.
When Bastien reported the violation, Daniel Mendler, the creator of
mimemagic, briefly changed the license on
mimemagic to GPL-2.0, forcing him to yank all early versions of the gem, which were under MIT.
Bastien reported a violation. Daniel followed through with fixing the problem, bringing all CI builds of Rails applications that had ActivaStorage (which depended on
marcel, which depended on
mimemagic) to a grinding halt.
Your bundle is locked to mimemagic (0.3.5), but that version could not be found in any of the sources listed in your Gemfile. If you haven't changed sources, that means the author of mimemagic (0.3.5) has removed it. You'll need to update your bundle to a version other than mimemagic (0.3.5) that hasn't been removed in order to install.
The dependency hierarchy looked something like this for some:
rails (~> 6.0.3, >= 184.108.40.206) was resolved to 220.127.116.11, which depends on activestorage (= 18.104.22.168) was resolved to 22.214.171.124, which depends on marcel (~> 0.3.1) was resolved to 0.3.3, which depends on mimemagic (~> 0.3.2)
For a brief moment, there was chaos. Some folks started demanding and commanding as if someone owed them something. Others tried to help.
An important thing to note here is an MIT-licensed code is GPL-compatible, but a GPL-licensed code is not MIT-compatible. This means you can include an MIT-licensed code in a GPL-licensed application, but you cannot include a GPL-licensed code in an MIT-licensed application. More on this later.
How Developers Worked Around The Issue
I heard people suggesting getting rid of ActiveStorage if your app didn’t use it.
Some got the MIME type database on their systems through Homebrew and updated
mimemagic, which looked in some paths, including where Homebrew may have installed the database.
brew install shared-mime-info bundle update nokogiri marcel mimemagic
Linux users did the equivalent for their distros.
Others suggested grabbing a copy of
mimemagic and putting it into
/vendor/gem and then updating the Gemfile to something like:
gem "mimemagic", path: "vendor/gems/mimemagic-0.3.6"
Another workaround was referencing the yanked gem. Yanking a gem only removes the code from the host, Rubygems. Github keeps another copy.
gem 'mimemagic', github: 'mimemagicrb/mimemagic', ref: '01f92d86d'
Rails Core Team Yanked Mimemagic
With all these slick interim fixes floating around, the Rails core team was working to figure out a more lasting solution. What they ended up doing is providing a bugfix release in Rails version 126.96.36.199 that removed the dependency on
marcel, an Active Storage dependency.
The Rails core team went with Apache Tika. Apache Tika provides capabilities for the identification of more than 1400 file types from the Internet Assigned Numbers Authority taxonomy of MIME types, similar to what
share-mime-info provides but with a permissive license – Apache License-2.0.
Open-Source Licensing 101
Before you start this section, here’s a disclaimer: I’ve never been to law school, and I’m no open-source licensing expert. Almost everything from this point forward is referenced from other resources that I link to at the end of the post.
With that out of the way, a software license is a grant of permission by the owner of a legal right (usually the creator of the code) to software (the licensor) for another person or entity (the licensee) to do something with the software.
The fundamental purpose of open source licensing is to deny anybody the right to exclusively exploit a work.
When a user buys a packaged product, most often than not, they are bound by what’s known as a “shrinkwrap contract” or a shrinkwrap license. A shrinkwrap license asserts that, by opening the plastic wrap of the product, the consumer is bound by a contract under which they cannot:
- Copy the work.
- Create derivate works based on the packaged content.
- Authorise anyone to do either of the points stated above.
The foundation of open-source licensing is to abolish these restrictions. The freedom to copy work and create derivatives from other people’s works means different things to different groups of people. This has given rise to a wide variety of licenses in the open-source field.
Among the numerous licenses are MIT and GPL, which fall under different licensing categories: Permissive and copyleft.
Permissive vs Copyleft Licenses
A permissive software license has minimal restrictions on how the software can be used, modified, and redistributed; like MIT. In other words, this type of license lets you do anything you want with the software as long as you provide attribution and don’t hold the creator of the software liable in case something goes wrong.
On the other hand, there’s a copyleft license. An example of such a license is the GPL. A copyleft license is a bit more restrictive. These type of licenses allow you to modify and freely distribute software, but with this freedom, you’re required to preserve these same rights in derivatives, i.e. code that based your work on.
In short, a permissive license allows “proprietization”. A copyleft license forbids it. With a permissive licence, you have exclusive rights to commercially exploit someone’s work.
You can tell from the image above that the difference between a permissive and a copyleft licence is the right to sublicense. What this means is, licensee or a second party can’t relicense a GPL-licensed code. i.e. you can’t grab and use a GPL codebase into your MIT codebase.
A Brief History Of GNU GPL
Richard Stallman, the original writer of the GPL license, worked on a Lisp interpreter that Symbolics Inc. (a now-defunct computer manufacturer) asked to use. Stallman gave up his version of his work on Lisp to Symbolics, granting them all rights.
When Stallman wanted to see how Symbolics had improved the Lisp interpreter, they refused. Stallman was like, “WTF!?! You inherited free software from me. Now you deny me access to see what you did with my software? This shit needs to stop!”
That is to say, proprietary modifications will not be allowed. I want to make sure that all versions of GNU remain free.
Stallman’s actions made the concept of “copyleft” mainstream, hence the reason we now have protective licenses like GNU GPL against permissive ones like Apache and MIT. The principle of demanding licenses of derivative works to be based on the original is called generational limitation.
Rails Is Guilty Of No License Violation
You can’t blame Rails for what happened with
mimemagic for two reasons:
- Rails included a gem that was licensed (incorrectly) under MIT.
- Rails is not a derivative work of
The United States Copyright Act of 1976, 17 USC. Section 101 states: A “derivative work” is a work based upon one or more preexisting work. I believe this definition is true in other jurisdictions, and to my understanding, Rails didn’t violate GPL because it imported a library that was a GPL derivative. Rails itself isn’t a derivative, they can cut out the “tainted” libraries anytime.
mimemagic had directly imported the
shared-mime-info database directly into the gem, making it a derivative of
shared-mime-info. Daniel Mendler was right in yanking earlier versions of
mimemagic to protect himself, even if he did so without notice.
Gratitude To Those Sustaining Open-Source
Amidst the short-lived brouhaha to the yanking emerged Jon Wood, who single-handedly carried many developers on his back to a solution. The Rails community is happy to have such folks around. For his efforts, we’re thankful.
Of course, the Rails Core Team, as always, promptly found a database with a permissive license to avert the problem. Kudos to the Rails team!
Understanding Open Source and Free Software Licensing, Andrew M St. Laurent
Ever Given meme: h/t @mahemoff