I've read a lot about this and know there are many related questions on here, but I couldn't find a definitive guide for how to go about sanitizing everything. One option is to sanitize on insert, for example I have the following in my model
before_validation :sanitize_content, :on => :create
def sanitize_content
self.content = ActionController::Base.helpers.sanitize(self.content)
end
Do I need to run this on every field in every model? I'm guessing the :on => :create should be removed too so it runs when updates too?
The other option is to sanitize when data is displayed in views, using simple_format, or .html_safe or sanitize(fieldname). SHould I be sanitizing in all my views for every single field, as well as on insert? Having to do this manually everywhere doesn't seem very railsy
Thanks for any help
Because I always appreciate when I find the source of knowledge and code on any SO answer, I will provide that for this question.
Both ActiveRecord and ActionController provide methods to sanitize sql input.
Specifically from
ActiveRecord::Sanitization::ClassMethods
you have sanitize_sql_for_conditions and its two other aliases: sanitize_conditions and sanitize_sql. The three do literally the exact same thing.sanitize_sql_for_conditions
However, in ActiveRecord you also have
sanitize_sql_for_assignment
whichOn the other hand, in ActionController you have
ActionController::Parameters
which allows you toThe parameters magic is called Strong Parameters, docs here.
I hope that helps anyone, if only to learn and demystify Rails! :)
TL;DR
Regarding user input and queries: Make sure to always use the active record query methods (such as
.where
), and avoid passing parameters using string interpolation; pass them as hash parameter values, or as parameterized statements.Regarding rendering potentially unsafe user-generated html / javascript content: As of Rails 3, html/javascript text is automatically properly escaped so that it appears as plain text on the page, rather than interpreted as html/javascript, so you don't need to explicitly sanitize (or use
<%= h(potentially_unsafe_user_generated_content)
%>If I understand you correctly, you don't need to worry about sanitizing data in this manner, as long as you use the active record query methods correctly. For example:
Lets say our parameter map looks like this, as a result of a malicious user inputting the following string into the
user_name
field:The bad way (don't do this):
The resulting query would look like:
Direct string interpolation in this manner will place the literal contents of the parameter value with key
:user_name
into the query without sanitization. As you probably know, the malicious user's input is treated as plain 'ol SQL, and the danger is pretty clear.The good way (Do this):
OR
The resulting query would look like:
So as you can see, Rails in fact sanitizes it for you, so long as you pass the parameter in as a hash, or method parameter (depending on which query method you're using).
The case for sanitization of data on creating new model records doesn't really apply, as the
new
orcreate
methods are expecting a hash of values. Even if you attempt to inject unsafe SQL code into the hash, the values of the hash are treated as plain strings, for example:Results in the query:
So, same situation as above.
I hope that helps. Let me know if I've missed or misunderstood anything.
Edit Regarding escaping html and javascript, the short version is that ERB "escapes" your string content for you so that it is treated as plain text. You can have it treated like html if you really want, by doing
your_string_content.html_safe
.However, simply doing something like
<%= your_string_content %>
is perfectly safe. The content is treated as a string on the page. In fact, if you examine the DOM using Chrome Developer Tools or Firebug, you should in fact see quotes around that string.