This project is archived and is in readonly mode.

#5719 ✓invalid

XSS hole in String % (with Hash) on 1.8

Reported by grosser | September 28th, 2010 @ 07:31 AM

("<a>%{x}</a>".html_safe % {:x=>'<script>y</script>'}).should ==
-> is <a><script>y</script></a>
-> is still html_safe?

This leads to xss holes when e.g. replacing words in translations.
normal %

"%s aa".html_safe % ['<script>x</script>']
is also affected

Comments and changes to this ticket

  • Bruno Michel

    Bruno Michel September 30th, 2010 @ 09:59 AM

    There is only a very restrictive set of operations on string that return html_safe strings (IIRC, <<, + and concat). Other operations return unsafe strings by design. For example, in Rails 3.0.0:

    ruby-1.9.2-p0 > ("%s aa".html_safe % ['<script>x</script>']).html_safe?
     => false 
    ruby-1.9.2-p0 > ("<a>%{x}</a>".html_safe % {:x=>'<script>y</script>'}).html_safe?
     => false

    So, there are no XSS holes, but if you want to preserve HTML markup from the original string, you have to do it yourself.

  • grosser

    grosser September 30th, 2010 @ 02:22 PM

    ahh % with array is not affected

    ree-1.8.7-2010.01 > ("%s aa".html_safe % ['<script>x</script>']).html_safe?
     => false

    but % with hash is:

    ree-1.8.7-2010.01 > ("<a>%{x}</a>".html_safe % {:x=>'<script>y</script>'}).html_safe?
     => true

    so maybe its a 1.8 bug

  • grosser

    grosser October 6th, 2010 @ 06:55 AM

    • Title changed from “html_safe is not honored by String#%” to “XSS hole in String % (with Hash) on 1.8”
  • David Trasbo

    David Trasbo October 8th, 2010 @ 09:23 AM

    • State changed from “new” to “invalid”
    • Importance changed from “” to “Low”

    I think this is a REE related issue. 1.8 doesn't even support the Hash syntax, and here's what happens on 1.9:

    ➜  irb
    ruby-1.9.2-p0 > require 'active_support/core_ext/string/output_safety'
     => true 
    ruby-1.9.2-p0 > ("%{foo}".html_safe % {:foo => '<script></script>'}).html_safe?
     => false

    Maybe REE's String#% manipulates self instead of making a new String object?

  • grosser

    grosser October 8th, 2010 @ 02:24 PM

    The i18n gem loaded by rails adds the % method supporting hash to string.
    (This kind of replacement is often used when adding something into translations.)

    ree-1.8.7-2010.01 > "%{x}y" %{:x=>1}
     => "1y"
  • David Trasbo

    David Trasbo October 8th, 2010 @ 03:21 PM

    Which means this is not Rails' but i18n's fault.

  • grosser

    grosser October 8th, 2010 @ 05:55 PM

    I think rails should take care of all html_safe related methods, so they do not get spread out into multiple places.

    My idea for a patch:

    if ("%{x}".html_safe%{:x=>1}).html_safe? # fix hash replacement being safe on ruby 1.8
      module HtmlSafePercent

    def %(*args)
    end String.send(:include, HtmlSafePercent) end
  • grosser

    grosser October 8th, 2010 @ 05:56 PM

    that should have been one block...

  • dncastilho (at gmail)

    dncastilho (at gmail) February 6th, 2011 @ 11:54 AM

    also affecting me on rails 3 + ruby 1.9.2 ... pretty annoying! does anyone have a patch suggestion for this?

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

<h2 style="font-size: 14px">Tickets have moved to Github</h2>

The new ticket tracker is available at <a href=""></a>