1

I'd like to implement a Content Security Policy (CSP) that's as strict as possible. According to this intro on CSP, inline styles are bad (emphasis mine):

Inline style is treated in the same way: both the style attribute and style tags should be consolidated into external stylesheets to protect against a variety of surprisingly clever data exfiltration methods that CSS enables.

If you really, absolutely must have inline script and style, you can enable it by adding 'unsafe-inline' as an allowed source in a script-src or style-src directive. But please don’t.

The default form_tag method inserts a hidden field for UTF-8 (I was actually looking for the authenticity token but cannot find it in my markup):

<div style="display:none"><input type="hidden" value="✓" name="utf8"></div>

which – because of display:none – gets reported in Firefox 32 as a violation of the following CSP:

$ curl -I http://localhost:3000 | grep Content-Security | fold
Content-Security-Policy-Report-Only: default-src https: 'self'; connect-src http
s: 'self'; font-src https: data:; frame-src https: 'self'; img-src https: 'self'
data:; media-src https: 'self'; object-src https: 'self'; script-src https: 'se
lf'; style-src https: 'self';

I'd like to disallow inline CSS styles in my CSP but Rails by default prevents that. What can I do?

awendt
  • 13,195
  • 5
  • 48
  • 66

1 Answers1

0

You could override the extra_tags_for_html method that ships with rails and just add a class that hides the div instead of adding it inline. Try adding this to a helper, but keep in mind that this will have an effect on every form on your site, which is what it sounds like you're looking for:

def extra_tags_for_form(html_options)
  authenticity_token = html_options.delete("authenticity_token")
  method = html_options.delete("method").to_s

  method_tag = case method
    when /^get$/ # must be case-insensitive, but can't use downcase as might be nil
      html_options["method"] = "get"
      ''
    when /^post$/, "", nil
      html_options["method"] = "post"
      token_tag(authenticity_token)
    else
      html_options["method"] = "post"
      method_tag(method) + token_tag(authenticity_token)
  end

  tags = utf8_enforcer_tag << method_tag
  #content_tag(:div, tags, :style => 'margin:0;padding:0;display:inline')
  content_tag(:div, tags, :class => 'hidden_form_field')
end

The original line is commented out and the line you need to replace it with is below. You'll also have to add this to a stylesheet to get the same visual effect:

.hidden_form_field {
  margin: 0;
  padding: 0;
  display: inline;
}

In essence, you're just overriding the rails method that wraps that div around the hidden form field.

NM Pennypacker
  • 6,704
  • 11
  • 36
  • 38