Software Engineering Techniques— Avoid leaking sensitive information with a tripwire
Avoid the all-to-common developer mistake of leaking sensitive information in an API.
A problem I’ve seen a lot is the back-end controller accidentally serializing and returning confidential data to the front-end.
Sensitive things like password hashes, API access credentials, etc. may accidentally be serialized by magic framework defaults.
Promiscuous serialization
It’s quite easy to accidentally do, especially on a large team with multiple projects. A lot of frameworks put convenience over security, serializing all fields by default in the absence of a whitelist.
As a result, common developer errors may contribute to hidden security vulnerabilities.
In Ruby on Rails, for example, not specifying a serializer when returning an object from a controller will simply return all of the attributes for that object.
class UsersController < ActionController:Base
# If there is no UsersSerializer, this method leaks sensitive data def show
user = User.find(params[:id])
render user
endendThis might happen in a lot of situations. A developer may forget to add the serializer. You may be working with a name-spaced model and the auto-magic resolution doesn’t kick in just right.
Even if you do specify a serializer, you’re not entirely safe. If that serializer uses relationships in the serializer, those relationships will have all of their attributes serialized as well:
class UsersController
def show
User.find(params[:id])
endendclass UsersSerializer
attributes :id, :name
has_many :secret_notes # leak!endYou can see there’s a lot of potential for data to be leaked — on larger teams it is inevitable for something to happen eventually.
How do you have secure defaults in an environment that fights against you?
Simple — use a tripwire.
A tripwire?
Tripwires are things that have an effect upon a certain trigger.
In this basic implementation, the tripwire is a field that, when serialized, will throw an error. You can do this in in the following way (example using Ruby on Rails):
Add an automatically serialized column to the table you want to protect
In the model, create a getter that throws an error
class User < ActiveRecord::Base def tripwire
raise 'default serialization is not allowed'
endendWhen the framework attempts to serialize this model using the default promiscuous method, it will encounter this field and throw an error, alerting the developer that something went wrong.
This tripwire optimizes the system in favor of failing early and preventing the leaking of sensitive information. It may result in an increase in errors if it ever makes it to production, but will prevent the greater issue of leaking sensitive data. Fail-open can lead to all sorts of confidentiality breaches, whereas the fail-closed technique of the tripwire can prevent these from happening at the cost of potentially preventing data access in legitimate situations.


