test/test_sanitize.rb in sanitize-2.1.0 vs test/test_sanitize.rb in sanitize-2.1.1

- old
+ new

@@ -53,14 +53,14 @@ :relaxed => '<p>a</p><blockquote>b</blockquote>' }, :malicious => { :html => '<b>Lo<!-- comment -->rem</b> <a href="javascript:pants" title="foo">ipsum</a> <a href="http://foo.com/"><strong>dolor</strong></a> sit<br/>amet <<foo>script>alert("hello world");</script>', - :default => 'Lorem ipsum dolor sit amet script&gt;alert("hello world");', - :restricted => '<b>Lorem</b> ipsum <strong>dolor</strong> sit amet script&gt;alert("hello world");', - :basic => '<b>Lorem</b> <a rel="nofollow">ipsum</a> <a href="http://foo.com/" rel="nofollow"><strong>dolor</strong></a> sit<br>amet script&gt;alert("hello world");', - :relaxed => '<b>Lorem</b> <a title="foo">ipsum</a> <a href="http://foo.com/"><strong>dolor</strong></a> sit<br>amet script&gt;alert("hello world");' + :default => 'Lorem ipsum dolor sit amet &lt;script&gt;alert("hello world");', + :restricted => '<b>Lorem</b> ipsum <strong>dolor</strong> sit amet &lt;script&gt;alert("hello world");', + :basic => '<b>Lorem</b> <a rel="nofollow">ipsum</a> <a href="http://foo.com/" rel="nofollow"><strong>dolor</strong></a> sit<br>amet &lt;script&gt;alert("hello world");', + :relaxed => '<b>Lorem</b> <a title="foo">ipsum</a> <a href="http://foo.com/"><strong>dolor</strong></a> sit<br>amet &lt;script&gt;alert("hello world");' }, :raw_comment => { :html => '<!-- comment -->Hello', :default => 'Hello', @@ -179,11 +179,11 @@ 'protocol-based JS injection: spaces and entities' => { :html => '<img src=" &#14; javascript:alert(\'XSS\');">', :default => '', :restricted => '', :basic => '', - :relaxed => '<img src="">' + :relaxed => '<img src>' } } describe 'Config::DEFAULT' do it 'should translate valid HTML entities' do @@ -643,5 +643,79 @@ it 'should not have Nokogiri 1.4.2+ unterminated script/style element bug' do Sanitize.clean!('foo <script>bar').must_equal('foo bar') Sanitize.clean!('foo <style>bar').must_equal('foo bar') end end + +describe 'Malicious HTML' do + make_my_diffs_pretty! + parallelize_me! + + before do + @s = Sanitize.new(Sanitize::Config::RELAXED) + end + + # libxml2 >= 2.9.2 doesn't escape comments within some attributes, in an + # attempt to preserve server-side includes. This can result in XSS since an + # unescaped double quote can allow an attacker to inject a non-whitelisted + # attribute. Sanitize works around this by implementing its own escaping for + # affected attributes. + # + # The relevant libxml2 code is here: + # <https://github.com/GNOME/libxml2/commit/960f0e275616cadc29671a218d7fb9b69eb35588> + describe 'unsafe libxml2 server-side includes in attributes' do + tag_configs = [ + { + tag_name: 'a', + escaped_attrs: %w[ action href src name ], + unescaped_attrs: [] + }, + + { + tag_name: 'div', + escaped_attrs: %w[ action href src ], + unescaped_attrs: %w[ name ] + } + ] + + before do + @s = Sanitize.new({ + elements: %w[ a div ], + + attributes: { + all: %w[ action href src name ] + } + }) + end + + tag_configs.each do |tag_config| + tag_name = tag_config[:tag_name] + + tag_config[:escaped_attrs].each do |attr_name| + input = %[<#{tag_name} #{attr_name}='examp<!--" onmouseover=alert(1)>-->le.com'>foo</#{tag_name}>] + + it 'should escape unsafe characters in attributes' do + @s.clean(input).must_equal(%[<#{tag_name} #{attr_name}="examp<!--%22%20onmouseover=alert(1)>-->le.com">foo</#{tag_name}>]) + end + + it 'should round-trip to the same output' do + output = @s.clean(input) + @s.clean(output).must_equal(output) + end + end + + tag_config[:unescaped_attrs].each do |attr_name| + input = %[<#{tag_name} #{attr_name}='examp<!--" onmouseover=alert(1)>-->le.com'>foo</#{tag_name}>] + + it 'should not escape characters unnecessarily' do + @s.clean(input).must_equal(input) + end + + it 'should round-trip to the same output' do + output = @s.clean(input) + @s.clean(output).must_equal(output) + end + end + end + end +end +