Build Status Code Climate Test Coverage Gem Version

Shields Up

This gem provides an alternative implementation of strong_parameters.

usage (the grammar for permit statements is the same as strong_parameters)

Differences to strong parameter

params.symbolize_keys (or similar functions) will disable strong_parameters protection silently. With ShieldsUp this can not happen. (For a more in depth explanation see this discussion on the rails core mailing list: https://groups.google.com/forum/#!topic/rubyonrails-core/TdQVJCw1HfI)

Enable ShieldsUp

in Gemfile

  gem 'shields_up'

in controllers

  include ShieldsUp
  • ShieldsUp::Parameters type only allows three operations: [], permit and require.
  • You can use symbols or strings to access variables.

Example:

params[:company] Or params["company"]

A more complicated example:

params.permit(:company => [:address, :enabled])

Or:

params.permit("company" => [:address, "enabled"])

How to disable shields up.

If you have a bunch of legacy code in a controller or you call into gems whose parameter handling you do not control (e.g. devise) you can disable shields_up at your own risk. Similar to holding a lock around critical sections these blocks should generally be kept as short as possible.


params.with_shields_down do
  call_some_legacy_stuff_or_gem()
end


  • with_shields_down can not be nested. This means inside with_shields_down there should be no with_shields_down
  • the places in an application disabling parameter protection are such explicit and can be accounted for during an audit

Common Pitfalls:

  • *to update and destroy associated records, permit :id, and :_destroy when you use accepts_nested_attributes_for in combination with a has_many association.

Example:

# To whitelist the following data:
# {"applicant" => {"email_address" => "[email protected]",
#                  "contact_info_attributes" => { "1" => {"salutation" => "First Salutation"},
#                                        "2" => {"salutation" => "Second Salutation"}}}}
    params.permit(
        {:applicant => [
            :email_address,
            {:contact_info_attributes => [:salutation, :id, :_destroy]},
        ]}
    )
  • use hash inside permit statment* for non scaler type.

Example:

# To whitelist the following data:
# {"applicant" => {"email_address" => "[email protected]",
#                  "info" => { "first_name" => 'First', "last_name" => 'Last'}}}

    params.permit(
        {:applicant => [
            :email_address,
            <b>{</b>:info => [:first_name, :last_name]<b>}</b>
        ]}
    )

Limitations

Similar to strong_parameters, this gem was designed with the most common use cases in mind. It is not meant as a silver bullet to handle all your whitelisting problems. However you can easily disable shields_up, and sanitize the parameter with your own code to adapt to your situation.

In order to keep our grammar compatible to strong_parameters it is not possible to express permission for array of arrays:

{'company' => [['a','b'],['a','b']]}