Just Because You Can Kill Someone With It Does Not Make It Insecure

7 minute read

This weekend, Github had what an impartial, understated observer might call a small dustup related to how the Rails web framework functions “out of the box”. For those amongst my non-technical audience (well, your eyes have probably glazed over at this point anyway), Github is a company that provides hosting of source code using a tool called Git. Github has become uniquely popular in the tech circles and hosts (insert some large number here) of projects, most of which are open source (which means not proprietary). Source control allows developers to track the history of code among other functions I won’t get into. If you are in the non-technical portion of my audience and are still reading, God bless you.

What happened at Github roughly goes like this. Github is built on Rails which is a hugely popular web framework that makes it dirt simple to create a pretty decent website. So at this point, we have the facts that Rails is hugely popular and Github is hugely popular. So lots of people are involved. Rails is what’s called an MVC framework. The MVC stands for Model-View-Controller. A Model is a representation of your data. A View is a way to display that data. A Controller facilitates the interaction between the two. This is a 10,000 foot view but will work for our purposes. In a real world example, you might have an ordering system for widgets. You might then have two views, one which shows you all the orders in your database and another that lets you create new orders. You would have an Order model that represented a physical order in the real world with customer information, product information, etc. The controller would manage interactions between the view and the model such as saving the order to the database, deleting orders, showing how many trillions of dollars you made last month selling widgets to Bill Gates, etc.

The beauty of Rails is that it makes it extremely easy to build a web site. You can go through this fantastic Rails tutorial in a weekend if you are motivated and starting writing a website on Monday. This was undoubtedly one of the goals of the creator of Rails because at every turn, when the decision is between hard or easy, he seems to have chosen easy. This is a GOOD THING. As with all GOOD THINGS (like scotch and kittens), decisions have to be made that may have some unpleasant side effects. Let’s go back to your trillion dollar widget web site. The only way an order should be able to get into your database (or be deleted more importantly) is through your view which of course you secured using authentication that is robust and thorough. However, in Rails, the models have what could be called a safety mechanism. The default behavior is that any attribute on a model (say Email on the Customer model) is open for mass assignment unless you, as the developer, take a certain precaution to prevent it. Mass assignment means that if an attacker gets control of the request between the web browser and the server, he can manipulate the data in the request to be whatever he wants. It’s right there in the documentation. This is a BAD THING in many people’s eyes.

Let’s take a little detour that might help. I have a gun (because I live in Texas and every one in Texas has a gun in the back of their pickup and a deer on the hood of the pickup.) The gun (you can assume I only have 1 gun for the purposes of this discussion but no one in Texas has one gun) I have is a Springfield XD 9MM semi-automatic pistol. I’m going to let you in on a little secret. My XD was created with the express intent and purpose of shooting bullets. The target of those bullets may vary but the general purpose of the gun is unchanged regardless of the target. It’s designed to shoot things.

However, luckily for me, the makers of the XD had the foresight to include mechanisms called safeties on my pistol. For the sake of this argument, you can also assume that all guns have safeties. This is probably not exactly true but the population of guns that don’t have safeties in this day and age is small enough to be ignored. Why does my gun have safeties? Because there are times when you would prefer that the gun did not go off when you pull the trigger. There are three safeties on my XD (other guns have one or two, it all depends on the make and model). The first is a trigger safety. It’s essentially a dual trigger that locks the main trigger in place so that it can’t go off if the gun is dropped or bumped. The second is a grip safety. It’s a small lever in the butt of the grip that must be fully and completely depressed before the gun can fire. This prevents accidental discharges if the trigger were to get caught on something. Finally, there is a loaded chamber indicator and a striker indicator that tell me when there is a round in the chamber and when the striker is cocked. This is more of a logical safety in that I can always be aware of the status of the pistol.

The safeties are nice but again I return to the essential raison d’être for any gun which is shoot bullets. If I pick up the gun, depress both safeties and there is a bullet in the chamber with the striker cocked, depressing the trigger will result in said bullet flying out the other end in the general direction the gun is pointing. This fact about guns does not entail A SECURITY VULNERABILITY. If I take a gun into a bank and start shooting people, the gun is not displaying some inherent security flaw. The operator of the gun has a personal responsibility to use the gun in morally and legally just ways. It is up to me as the shooter of the gun to know and be cognizant of this fact. There are ways to make a gun perfectly safe and they turn it into an expensive paper weight because the only way a gun is perfectly safe is if it is physically impossible to get a bullet to come out the business end of the gun. But then we don’t really have a gun, do we?

What does this all have to do with the Rails issues at Github (other than the fact you may want to shoot yourself if you’re still reading)? It is my contention (and this is mostly conjecture but reasonably based conjecture in that Rails has a philosophy and mass assignment fits that philosophy) that it is the express intent of Rails to make building websites easy. If Rails forced developers to prevent mass assignment on all models, it would be distinctly harder to build web sites. However, Rails does have a mechanism for preventing mass assignment and it’s detailed right there in the docs and the tutorial. Rails essentially says this: “I don’t want to get in your way of building web sites so there are features of Rails that make it easier to build websites at the expense of possibly doing something that allows people to hose up your website. Use at your own damn risk.”

There are a lot of people weighing in on this issue at Github and many of them seem to think that mass assignment is a security vulnerability inherent in Rails. I do not see how this is the case. Just as the gun has no way of knowing if I’m shooting innocent people in a bank or paper targets at the range, Rails has no way of knowing what attributes of any model you want exposed for assignment. It’s not the gun’s or Rails duty to police your behavior. As a user of Rails, you have the responsibility to understand the framework and work within the limits and guidances it provides you. I would argue that Rails even goes farther than the safeties on the gun because it has an explicit way to prevent mass assignment which keeps an attacker from destroying your web site. If you choose to avoid the safeties built into Rails, it’s your fault if you kill someone. That does not make Rails inherently insecure.

Anything in the world can be perfectly safe but it’s always at the cost of perfect liberty. It’s a tradeoff we make constantly at all kinds of levels. It strikes me as coming down far too near the perfectly safe side to advocate mass assignment as a security vulnerability in Rails. We could make Rails perfectly safe but then it stops being a framework that enables you to build web sites easily and becomes something else entirely. Take some personal responsibility for your actions and do the legwork required to properly use the framework.