CVE-2020-4054 (Ruby, published 2020-06-16T22:15Z)
Description: value: In Sanitize (RubyGem sanitize) greater than or equal to 3.0.0 and less than 5.2.1, there is a cross-site scripting vulnerability. When HTML is sanitized using Sanitize's "relaxed" config, or a custom config that allows certain elements, some content in a math or svg element may not be sanitized correctly even if math and svg are not in the allowlist. You are likely to be vulnerable to this issue if you use Sanitize's relaxed config or a custom config that allows one or more of the following HTML elements: iframe, math, noembed, noframes, noscript, plaintext, script, style, svg, xmp. Using carefully crafted input, an attacker may be able to sneak arbitrary HTML through Sanitize, potentially resulting in XSS (cross-site scripting) or other undesired behavior when that HTML is rendered in a browser. This has been fixed in 5.2.1.
Severity: MEDIUM (CVSS v3 base score: 7.3)
Weakness: CWE-79 \u2014 Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
Repository: https://github.com/rgrove/sanitize
Files changed:
README.md
lib/sanitize/config/default.rb
test/test_clean_element.rb
test/test_malicious_html.rb
Commit message: Fix sanitization bypass in HTML foreign content

https://github.com/rgrove/sanitize/security/advisories/GHSA-p4x4-rw2p-8j8m


Vulnerable code:
        iframe noembed noframes noscript script style
    it 'should escape the content of removed `plaintext` elements' do
      Sanitize.fragment('<plaintext>hello! <script>alert(0)</script>')
        .must_equal 'hello! &lt;script&gt;alert(0)&lt;/script&gt;'
    end

    it 'should escape the content of removed `xmp` elements' do
      Sanitize.fragment('<xmp>hello! <script>alert(0)</script></xmp>')
        .must_equal 'hello! &lt;script&gt;alert(0)&lt;/script&gt;'
    end


Fixed code:
However, please note that Sanitize _cannot_ fully sanitize the contents of
`<math>` or `<svg>` elements, since these elements don't follow the same parsing
rules as the rest of HTML. If this is something you need, you may want to look
for another solution.

**Warning:** Sanitize cannot fully sanitize the contents of `<math>` or `<svg>`
elements, since these elements don't follow the same parsing rules as the rest
of HTML. If you add `math` or `svg` to the allowlist, you must assume that any
content inside them will be allowed, even if that content would otherwise be
removed by Sanitize.

        iframe math noembed noframes noscript plaintext script style svg xmp
    it 'should not preserve the content of removed `math` elements' do
      Sanitize.fragment('<math>hello! <script>alert(0)</script></math>')
        .must_equal ''
    end

    it 'should not preserve the content of removed `plaintext` elements' do
      Sanitize.fragment('<plaintext>hello! <script>alert(0)</script>')
        .must_equal ''
    end

    it 'should not preserve the content of removed `svg` elements' do
      Sanitize.fragment('<svg>hello! <script>alert(0)</script></svg>')
        .must_equal ''
    end

    it 'should not preserve the content of removed `xmp` elements' do
      Sanitize.fragment('<xmp>hello! <script>alert(0)</script></xmp>')
        .must_equal ''
    end


  # https://github.com/rgrove/sanitize/security/advisories/GHSA-p4x4-rw2p-8j8m
  describe 'foreign content bypass in relaxed config' do
    it 'prevents a sanitization bypass via carefully crafted foreign content' do
      %w[iframe noembed noframes noscript plaintext script style xmp].each do |tag_name|
        @s.fragment(%[<math><#{tag_name}>/*&lt;/#{tag_name}&gt;&lt;img src onerror=alert(1)>*/]).
          must_equal ''

        @s.fragment(%[<svg><#{tag_name}>/*&lt;/#{tag_name}&gt;&lt;img src onerror=alert(1)>*/]).
          must_equal ''
      end
    end
  end