Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 134 lines (83 sloc) 4.814 kb
97e8705 @dcunning initial version to keep your controllers secure by default
dcunning authored
1 # ParamAccessible
2
3 [![Build Status](https://secure.travis-ci.org/topdan/param_accessible.png)](https://secure.travis-ci.org/topdan/param_accessible.png)
4
5 Provides a method to help protect your Ruby on Rails controllers from malicious or accidentally destructive user parameters. It is independent, but heavily influenced by param_protected.
6
7 Make all your controllers secure by default as well as provide readable messages to users when a security breach was prevented.
8
9 For more information on the design considerations please visit: https://www.topdan.com/ruby-on-rails/params-accessible.html
10
11 ## Installation
12
13 Add this line to your application's Gemfile:
14
15 gem 'param_accessible'
16
17 And then execute:
18
19 $ bundle
20
21 Or install it yourself as:
22
23 $ gem install param_accessible
24
25 ## Usage
26
a15d603 @dcunning numbers are blocking the code tags
dcunning authored
27 This gem does not add any functionality by default. To activate it create a before_filter in any ActionController::Base subclass. We only use the filter for create and update actions because those are the normally only the only harmful ones:
019f9e6 @dcunning more usage and better examples
dcunning authored
28
29 before_filter :ensure_params_are_accessible, :only => [:create, :update]
30
0dfad2f @dcunning updated readme for regex stuff
dcunning authored
31 Now let's expose the parameters that are common across our application:
019f9e6 @dcunning more usage and better examples
dcunning authored
32
0dfad2f @dcunning updated readme for regex stuff
dcunning authored
33 param_accessible :page, :sort
34
35 You may want to allow all base-level parameters since most Rails controllers only send nested parameters to models (i.e. params[:user]):
36
37 # allow all base parameters (// is a regex that matches all strings)
38 param_accessible //
39
40 # allow any base parameter starting with "my_"
41 param_accessible /^my_/
019f9e6 @dcunning more usage and better examples
dcunning authored
42
a15d603 @dcunning numbers are blocking the code tags
dcunning authored
43 We also want to make sure only admins can change a user's "is_admin" and "is_active" attributes:
019f9e6 @dcunning more usage and better examples
dcunning authored
44
45 param_accessible :user => [:is_admin, :is_active], :if => :is_admin?
46
a15d603 @dcunning numbers are blocking the code tags
dcunning authored
47 Rinse and repeat for all your controllers and you're Rails Application will be much safer.
019f9e6 @dcunning more usage and better examples
dcunning authored
48
49 ## Example
50
0dfad2f @dcunning updated readme for regex stuff
dcunning authored
51 Placing the before_filter in our ApplicationController makes all our create and update actions secure by default. We also expose application-wide parameters and provide a friendly error message when an invalid parameter is provided.
019f9e6 @dcunning more usage and better examples
dcunning authored
52
97e8705 @dcunning initial version to keep your controllers secure by default
dcunning authored
53 class ApplicationController < ActionController::Base
54
55 # make all your controllers secure by default
56 before_filter :ensure_params_are_accessible, :only => [:create, :update]
57
0dfad2f @dcunning updated readme for regex stuff
dcunning authored
58 # expose the your common application parameters
59 param_accessible :page, :sort
97e8705 @dcunning initial version to keep your controllers secure by default
dcunning authored
60
76d5031 @dcunning typos
dcunning authored
61 # this error is thrown when the user submits an inaccessible param
97e8705 @dcunning initial version to keep your controllers secure by default
dcunning authored
62 rescue_from ParamAccessible::Error, :with => :handle_param_not_accessible
63
64 protected
65
66 def handle_param_not_accessible e
76d5031 @dcunning typos
dcunning authored
67 flash[:error] = "You gave me some invalid parameters: #{e.inaccessible_params.join(', ')}"
97e8705 @dcunning initial version to keep your controllers secure by default
dcunning authored
68 redirect_to :back
69 end
70
71 end
019f9e6 @dcunning more usage and better examples
dcunning authored
72
73 Inheriting from the class above, we now need to specify our accessible parameters for the create and update actions.
74
76d5031 @dcunning typos
dcunning authored
75 class UsersController < ApplicationController
97e8705 @dcunning initial version to keep your controllers secure by default
dcunning authored
76
77 # these attributes are available for everyone
019f9e6 @dcunning more usage and better examples
dcunning authored
78 param_accessible :user => [:name, :email, :password, :password_confirmation]
97e8705 @dcunning initial version to keep your controllers secure by default
dcunning authored
79
80 # these attributes are only available if the controller instance method is_admin? is true
019f9e6 @dcunning more usage and better examples
dcunning authored
81 param_accessible :user => [:is_admin, :is_locked_out], :if => :is_admin?
97e8705 @dcunning initial version to keep your controllers secure by default
dcunning authored
82
83 def update
84 @user = User.find(params[:id])
85
86 # this is now safe!
87 if @user.update_attributes(params[:user])
88 ...
89 else
90 ...
91 end
92 end
93 end
019f9e6 @dcunning more usage and better examples
dcunning authored
94
95 Showcase a helper module for handling errors and some more options.
96
97e8705 @dcunning initial version to keep your controllers secure by default
dcunning authored
97 class DemoController < ApplicationController
98
99 # rescue_from ParamAccessible::Error and respond with a 406 Not Acceptable status
100 # with an HTML, JSON, XML, or JS explanation of which parameters were invalid
101 include ParamAccessible::NotAcceptableHelper
102
103 param_accessible :foo, :if => :is_admin
104 param_accessible :bar, :unless => :logged_in?
105 param_accessible :baz, :only => :show
106 param_accessible :nut, :except => :index
107
108 end
019f9e6 @dcunning more usage and better examples
dcunning authored
109
110 Using Rails' skip_before_filter to make a controller insecure again
111
97e8705 @dcunning initial version to keep your controllers secure by default
dcunning authored
112 class InsecureController < ApplicationController
113
114 # skip the filter ApplicationController set up to avoid the accessible parameter checks
115 skip_before_filter :ensure_params_are_accessible
116
117 end
f842c6c @dcunning note the TODO's in the readme
dcunning authored
118
119 ## TODO
120
121 * Mark a parameter that expects an array as its value:
122 * param_accessible :user => ["group_ids[]"]
123 * would accept [10,12] or {"0" => 10, "1" => 12}
124 * param_accessible :user => {"groups[]" => [:name]}
125 * would accept [{:name => "Admins"}, {:name => "Users"}]
126
97e8705 @dcunning initial version to keep your controllers secure by default
dcunning authored
127 ## Contributing
128
129 1. Fork it
130 2. Create your feature branch (`git checkout -b my-new-feature`)
131 3. Commit your changes (`git commit -am 'Added some feature'`)
132 4. Push to the branch (`git push origin my-new-feature`)
133 5. Create new Pull Request
Something went wrong with that request. Please try again.