VYPR
Moderate severityNVD Advisory· Published Dec 7, 2009· Updated Apr 23, 2026

CVE-2009-4214

CVE-2009-4214

Description

Cross-site scripting (XSS) vulnerability in the strip_tags function in Ruby on Rails before 2.2.s, and 2.3.x before 2.3.5, allows remote attackers to inject arbitrary web script or HTML via vectors involving non-printing ASCII characters, related to HTML::Tokenizer and actionpack/lib/action_controller/vendor/html-scanner/html/node.rb.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
railsRubyGems
< 2.2.22.2.2
railsRubyGems
>= 2.3.0, < 2.3.52.3.5

Affected products

56
  • Rubyonrails/Rails44 versions
    cpe:2.3:a:rubyonrails:rails:0.10.0:*:*:*:*:*:*:*+ 43 more
    • cpe:2.3:a:rubyonrails:rails:0.10.0:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:0.10.1:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:0.11.0:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:0.11.1:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:0.12.0:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:0.12.1:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:0.13.0:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:0.13.1:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:0.14.1:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:0.14.2:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:0.14.3:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:0.14.4:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:0.9.1:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:0.9.2:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:0.9.3:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:0.9.4:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:0.9.4.1:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:1.0.0:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:1.1.0:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:1.1.1:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:1.1.2:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:1.1.3:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:1.1.4:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:1.1.5:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:1.1.6:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:1.2.0:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:1.2.1:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:1.2.2:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:1.2.3:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:1.2.4:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:1.2.5:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:1.2.6:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:1.9.5:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:2.0.0:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:2.0.0:rc1:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:2.0.0:rc2:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:2.0.1:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:2.0.2:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:2.0.4:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:2.1.0:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:2.1.1:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:2.3.2:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:2.3.3:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:2.3.4:*:*:*:*:*:*:*
  • cpe:2.3:a:rubyonrails:ruby_on_rails:*:*:*:*:*:*:*:*+ 10 more
    • cpe:2.3:a:rubyonrails:ruby_on_rails:*:*:*:*:*:*:*:*range: <=2.1.2
    • cpe:2.3:a:rubyonrails:ruby_on_rails:0.5.0:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:ruby_on_rails:0.5.5:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:ruby_on_rails:0.5.6:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:ruby_on_rails:0.5.7:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:ruby_on_rails:0.6.0:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:ruby_on_rails:0.6.5:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:ruby_on_rails:0.7.0:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:ruby_on_rails:0.8.0:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:ruby_on_rails:0.8.5:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:ruby_on_rails:0.9.0:*:*:*:*:*:*:*
  • ghsa-coords
    Range: < 2.2.2

Patches

1
bfe032858077

Make sure strip_tags removes tags which start with a non-printable character

https://github.com/rails/railsGabe da SilveiraNov 17, 2009via ghsa
2 files changed · +2 1
  • actionpack/lib/action_controller/vendor/html-scanner/html/node.rb+1 1 modified
    @@ -162,7 +162,7 @@ def parse(parent, line, pos, content, strict=true)
               end
               
               closing = ( scanner.scan(/\//) ? :close : nil )
    -          return Text.new(parent, line, pos, content) unless name = scanner.scan(/[\w:-]+/)
    +          return Text.new(parent, line, pos, content) unless name = scanner.scan(/[-:\w\x00-\x09\x0b-\x0c\x0e-\x1f]+/)
               name.downcase!
       
               unless closing
    
  • actionpack/test/controller/html-scanner/sanitizer_test.rb+1 0 modified
    @@ -19,6 +19,7 @@ def test_strip_tags
         assert_equal "This has a  here.", sanitizer.sanitize("This has a <!-- comment --> here.")
         assert_equal "This has a  here.", sanitizer.sanitize("This has a <![CDATA[<section>]]> here.")
         assert_equal "This has an unclosed ", sanitizer.sanitize("This has an unclosed <![CDATA[<section>]] here...")
    +    assert_equal "non printable char is a tag", sanitizer.sanitize("<\x07a href='/hello'>non printable char is a tag</a>")
         [nil, '', '   '].each { |blank| assert_equal blank, sanitizer.sanitize(blank) }
       end
     
    

Vulnerability mechanics

Root cause

"The strip_tags function's tokenizer fails to recognize HTML tags that begin with non-printing ASCII characters, causing them to be treated as text rather than stripped."

Attack vector

An attacker can inject arbitrary HTML or JavaScript by prefixing a tag with a non-printing ASCII character (e.g., \x07, \x00-\x09, \x0b-\x0c, \x0e-\x1f). Because the tokenizer's regex [CWE-79] only matched `[\w:-]+` for tag names, a tag like `<\x07a href='...'>` was not recognized as a tag and was passed through as text. When this unsanitized output is rendered in a victim's browser, the browser interprets the content as a valid HTML tag, executing the attacker's script.

Affected code

The vulnerability is in `actionpack/lib/action_controller/vendor/html-scanner/html/node.rb` within the `parse` method of the `Tag` class. The regex `scanner.scan(/[\w:-]+/)` on line 165 (pre-patch) fails to match tag names that begin with non-printing ASCII characters, causing the tokenizer to return a `Text` node instead of a `Tag` node. This affects the `strip_tags` function used throughout Rails views and sanitization helpers.

What the fix does

The patch [patch_id=25] modifies the regex in `node.rb` from `[\w:-]+` to `[-:\w\x00-\x09\x0b-\x0c\x0e-\x1f]+`. This expanded character class now includes non-printing ASCII characters (control characters in the ranges \x00-\x09, \x0b-\x0c, \x0e-\x1f) as valid tag-name characters. When the tokenizer encounters a tag starting with such a character, it now correctly identifies it as a tag and strips it, rather than falling through to return a `Text` node that would be rendered unsanitized. The accompanying test confirms that `<\x07a href='/hello'>` is now properly stripped.

Preconditions

  • inputThe application must use strip_tags or a sanitizer that relies on the vulnerable tokenizer to process user-supplied input.
  • networkThe attacker must be able to submit input containing non-printing ASCII characters (e.g., via form fields, URL parameters, or API payloads) that is later rendered in a web page served to other users.

Generated on May 19, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

18

News mentions

0

No linked articles in our index yet.