Simple_form: Error messages aren't rendered with html_safe anymore

Created on 26 Mar 2015  Â·  6Comments  Â·  Source: heartcombo/simple_form

Hi, sometimes I need to put some html to error messages:
simple_form

In 3.0.2 that worked, in 3.1.0 it doesn't.

Most helpful comment

@heaven If your error is something like this:

errors.add :invalid, "#{name} is invalid"
# or

errors.add :invalid, name: name

en:
  ...
    invalid: "%{name} is invalid"

And we just html safe whatever is in the error, we are opening your application to XSS because name could be anything, if the user can change this field. We prefer to play on the safe side here.

If you need the html portion in your form, and you're pretty sure there's no harm on it, you can pass the error by yourself on these rare cases as well:

f.input :zomg, error: f.object.errors[:zomg].first.try(:html_safe)

Or something like that. If you want that functionality back you could monkey patch Simple Form in your app, for example rewriting this method, and mark all errors as html safe back again - but now it's up to you to check if you have or not a case like I mentioned above.

It's all about being a bit more secure, unfortunately there are bad people out there, and we have to play on the safe side.

Thanks.

All 6 comments

Hi, this was a security change. If you trust your error content you can mark it as html safe. You can find more info here

Hi, ok, thanks, but I don't see how do I render my error messages, defined in en.yml with html_safe?

I believe simple form should not do anything like that, if developers allow users to pass labels – ok, it is their pain to escape them properly. But why escaping validation errors? It seems like a regression to me, you took care about those 0.1% of rare cases when users can pass html content and left 99% of simple form users without a solution.

@heaven If your error is something like this:

errors.add :invalid, "#{name} is invalid"
# or

errors.add :invalid, name: name

en:
  ...
    invalid: "%{name} is invalid"

And we just html safe whatever is in the error, we are opening your application to XSS because name could be anything, if the user can change this field. We prefer to play on the safe side here.

If you need the html portion in your form, and you're pretty sure there's no harm on it, you can pass the error by yourself on these rare cases as well:

f.input :zomg, error: f.object.errors[:zomg].first.try(:html_safe)

Or something like that. If you want that functionality back you could monkey patch Simple Form in your app, for example rewriting this method, and mark all errors as html safe back again - but now it's up to you to check if you have or not a case like I mentioned above.

It's all about being a bit more secure, unfortunately there are bad people out there, and we have to play on the safe side.

Thanks.

real code from a working application:

f.input :license_number, error: error_sub(f, :license_number, /sign in(?=\?\Z)/, link_to('sign in', new_session_url, remote: request.xhr?))

and in a helper:

  def error_sub(form, field, re, html)
    err_str = form.object.errors[field].first
    return nil unless err_str.present?
    new_err = ERB::Util.html_escape(err_str).gsub(re, html)
    new_err.html_safe
  end

Now I can use "%{value} is already registered. Did you want to sign in?" as error string with correct safe escaping of user input, but not of my link. The regular expression is anchored exactly where I want it with a positive lookahead assertion, in case some funny person submits "sign in" as input data.

Downside: now the view is coupled to the i18n.

why it can't be resolved by marking key from locale as in rails http://guides.rubyonrails.org/i18n.html#using-safe-html-translations? let's say i have a base error and would like to put there link from locale.

Was this page helpful?
0 / 5 - 0 ratings