Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails 4 parameters; how to whitelist a param to a set of values

I have already read some posts, such as Value whitelist using strong parameters in Rails 4, but it's not quite what I need.

I have a controller which takes an ID and loads a model. It also optionally takes a query string param (style) which can be one of 3 values, small, medium or large. This is passed to a method on the model which uses it to fetch an attached image (using paperclip). I noticed that if I pass an invalid param (eg style=wibble), then I get a 400 error and a notice that the internal file path doesn't exist. Brakeman also notes this as a security issue...

def show
  style = params[:style] || :medium

  thing = Model.find(params[:id])

  path = "#{Rails.root}/public#{thing.image_url(style)}"
  content_type = thing.image.content_type || 'image/png'
  send_file path, type: content_type, disposition: 'inline'
end

We use ActionController Parameters elsewhere to great effect; but I cannot see how that could "whitelist" a parameters options? Everywhere I have seen says to use a model validator, but that's assuming I'm submitting a parameter to update a model, which I am not.

I'm aware I could do something like:

return head :not_found unless %w(small medium large).include? style

Is this the best way?

like image 544
Nick Avatar asked Aug 02 '17 18:08

Nick


2 Answers

I wrote a gem that extends ActionController::Parameters for exactly this purpose: whitelisting parameter values. It's simple and lightweight. You would use it like this:

def model_params
  params.require(:model).permit(:style, :other_attribute).allow(style: %w[small medium large])
end

Hope you find it useful

https://github.com/msimonborg/allowable

like image 69
m. simon borg Avatar answered Nov 17 '22 18:11

m. simon borg


First, you need to define a Constant white-listing all the valid style values (I would argue that size_type is a more explicit name). (Watch out for the Symbol / String comparisons).

Then, you either return a 404 if the params[:style] is not included in the white-listed values OR you fallback to 'medium':

style = Model::AVAILABLE_SIZE_TYPES.include?(params[:style]) ? params[:style] || Model::AVAILABLE_SIZE_TYPES.first

Personally, I don't like fallbacks for user's input. They did something wrong (manipulated the URL, changed a value in a form, etc), they deserve to get an error page.

I implied the constant is defined in the Model, but it should not be there as it is not related to the business logic but related to the display of the Model. If you have a ModelDecorator, define it there.

like image 25
MrYoshiji Avatar answered Nov 17 '22 19:11

MrYoshiji