Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

XSS hole in String % (with Hash) on 1.8

#5719
("<a>%{x}</a>".html_safe % {:x=>'<script>y</script>'}).should ==
   "<a>&ltscript&gty&lt/script&gt</a>"
-> 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

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

State: invalid
Milestone: none
Assigned to: nobody
Importance: Low

Activity

  1. Bruno Michel
    Bruno Michel

    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.

    September 30th, 2010 @ 09:59 AM

  2. grosser
    grosser

    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

    September 30th, 2010 @ 02:22 PM

  3. grosser
    grosser
    • Title changed from html_safe is not honored by String#% to XSS hole in String % (with Hash) on 1.8

    October 6th, 2010 @ 06:55 AM

  4. David Trasbo
    David Trasbo
    • 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?

    October 8th, 2010 @ 09:23 AM

  5. grosser
    grosser

    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"
    

    October 8th, 2010 @ 02:24 PM

  6. David Trasbo
    David Trasbo

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

    October 8th, 2010 @ 03:21 PM

  7. grosser
    grosser

    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)
      String.new(super)
    end
    
    
    
    
    end String.send(:include, HtmlSafePercent) end

    October 8th, 2010 @ 05:55 PM

  8. grosser
    grosser

    that should have been one block...

    October 8th, 2010 @ 05:56 PM

  9. dncastilho (at gmail)
    dncastilho (at gmail)

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

    February 6th, 2011 @ 11:54 AM