Posted about 5 years ago. Visible to the public. Repeats.

Common mistakes when storing file uploads with Rails

1. Saving files to a directory that is not shared between deploys or servers

If you save your uploads to a made up directory like "RAILS_ROOT/uploads", this directory goes away after every deploy (since every release gets a new). Also this directory is not shared between multiple application servers, so your uploads are randomly saved to one local filesystem or another. Fixing this afterwards is a lot of fun.

Only two folders are, by default, shared between our application servers and deployments: "RAILS_ROOT/storage" and "RAILS_ROOT/public/system" (note that this might be different if you are not hosting at makandra).

2. Publishing confidential files to the whole Internet

All files in public/system are publicly accessible and requests will not touch your Rails application. Users can usually download your entire file catalog by seeing one path like "public/system/images/4.jpg" and then replacing the record ID (4) with values from 1 to 9999999999.

So don't store confidential stuff in there. Non-public files should by default go into /storage and should be delivered from a Rails controller action (e.g. /images/4/download) by using send_file. Since Rails code is doing the delivery you can do your usual authentication and authorization beforehand.

There are few exceptions where you want to store confidential files in the public folder. E.g. you need to deliver many thumbnails for an image gallery and don't want to spawn 50 Rails processes to deliver the image. In that case you can store the images in public/system but use for the path a non-guessable hash of e.g. the record ID and the application's secret token. So virtual paths need to look like "/public/system/images/5/ab4543fa3ecf44/image.jpg". For instructions for Paperclip see our card Deliver Paperclip attachments to authorized users only. Apply similiar techniques to Carrierwave etc..

3. Using the same storage folder for multiple Rails environments or test processes

This one affects your developers. If an image with ID 4 always ends up as public/system/images/4.jpg, multiple Rails environments (e.g. development and test) will randomly see and overwrite each other's files. See Always store your Paperclip attachments in a separate folder per environment for instructions how to fix this in Paperclip. Apply similiar techniques to Carrierwave etc.

4. Ignoring existing files when changing your storage paths

When you change your applications (e.g. because you follow the advice in this post) you must migrate files that are already stored on your staging and production servers. If the application hasn't seen production yet, check with your client if you can simply wipe all images/documents/whatever. But don't display broken images, it's unprofessional und looks like you screwed up.

5. Rails 2: Forgetting to add the multipart option to your upload form

When uploading files, you must set the multipart option like this in very old versions of Rails:

Copy
form_for @invoice, :html => { :multipart => true } do

If you do not, Rails will only receive the file name.

Does your version of Ruby on Rails still receive security updates?
Rails LTS provides security patches for old versions of Ruby on Rails (3.2 and 2.3).

Owner of this card:

Avatar
Henning Koch
Last edit:
6 months ago
by Henning Koch
About this deck:
We are makandra and do test-driven, agile Ruby on Rails software development.
License for source code
Posted by Henning Koch to makandra dev
This website uses cookies to improve usability and analyze traffic.
Accept or learn more