---
title: Prevent Spoofing with Paperclip
teaser: |
  Paperclip 4.0 and 4.1 contain security fixes to prevent spoofing.
  A content type or filename validation is also now required.
tags: web,ruby,paperclip,open source
author: Jon Yurek
published_on: 2014-02-14
---

[Egor Homakov] recently brought to my attention a slight problem with how
[Paperclip] handles some content type validations. Namely, if an attacker puts
an entire <abbr title="HyperText Markup Language">HTML</abbr> page into the EXIF
tag of a completely valid JPEG and named the file "gotcha.html", they could
potentially trick users into an XSS vulnerability.

Now, this is kind of a convoluted means of attacking. It involves:

* A server that's running Paperclip configured to not validate content types or
  filenames
* A front-end HTTP server that will serve the assets with a content type based
  on their file name
* The attacker must get the user to load the crafted image directly (injecting
  it in an `img` tag is not enough)

Even with this list of requirements, it's possible, and so we need to take it seriously.

## Content Type Spoof Detection

To combat this, we've released Paperclip 4.0 (and then quickly released 4.1),
which has a few new restrictions in order to improve out-of-the-box security.
The change that handles this problem directly is an automatic validation that
checks uploaded files for content type spoofing. That is, if you upload a JPEG
and name it `.html`, it's not going to get through. This happens automatically
during the upload process, and uses the `file` command in order to determine the
actual content type of the file. If you don't have `file` already (for example,
because you're on Windows), you can install [the file command] separately.

## Required Content Type or Filename Validations

Next, we're also turning on a new requirement: You must have a content type or
filename validation, or you must explicitly opt-out of it.

```ruby
class ActiveRecord::Base
  has_attached_file :avatar

  # Validate content type
  validates_attachment_content_type :avatar, :content_type => /\Aimage/

  # Validate filename
  validates_attachment_file_name :avatar, :matches => [/png\Z/, /jpe?g\Z/]

  # Explicitly do not validate
  do_not_validate_attachment_file_type :avatar
end
```

Note that older versions of Paperclip are susceptible to this attack if you
don't have a content type validation. If you do have one, then you are protected
against people crafting images to perform this type of attack.

The filename validation is new with 4.0.0. We know that some people don't store
the content types on their models, but still need a way to be valid. Using the
file name can help ensure you're only getting the kinds of files you expect, and
all Paperclip attachments have that. This will allow those users to upgrade
without having to implement a possibly costly migration of that data into their
database.

## Content Type Mapping

Immediately, some users reported problems with the spoof detection added in 4.0.
In order to fix this, we released 4.1 that added an option called
`:content_type_mappings` that will allow you to specify an extension that cannot
otherwise be mapped. For example:

```ruby
Paperclip.options[:content_type_mappings] = {
  :pem => "text/plain"
}
```

This will allow users to upload ".pem" files (public certificates for
encryption), because `file` considers those files as "text/plain". This will
tell Paperclip "I consider a .pem file that `file` calls 'text/plain' to be
correct" and it will accept it.

[Egor Homakov]: http://homakov.blogspot.com/2014/02/paperclip-vulnerability-leading-to-xss.html
[the file command]: http://gnuwin32.sourceforge.net/packages/file.htm
[Paperclip]: https://github.com/thoughtbot/paperclip
