Moderate severityNVD Advisory· Published Feb 14, 2011· Updated Apr 29, 2026
CVE-2011-0446
CVE-2011-0446
Description
Multiple cross-site scripting (XSS) vulnerabilities in the mail_to helper in Ruby on Rails before 2.3.11, and 3.x before 3.0.4, when javascript encoding is used, allow remote attackers to inject arbitrary web script or HTML via a crafted (1) name or (2) email value.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
actionpackRubyGems | < 2.3.11 | 2.3.11 |
actionpackRubyGems | >= 3.0.0, < 3.0.4 | 3.0.4 |
actionviewRubyGems | < 2.3.11 | 2.3.11 |
actionviewRubyGems | >= 3.0.0, < 3.0.4 | 3.0.4 |
Affected products
32cpe:2.3:a:rubyonrails:rails:2.0.0:*:*:*:*:*:*:*+ 29 more
- 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.1.2:*:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:2.2.0:*:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:2.2.1:*:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:2.2.2:*:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:2.3.10:*:*:*:*:*:*:*
- 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:rails:2.3.9:*:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.0.0:*:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.0.0:beta:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.0.0:beta2:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.0.0:beta3:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.0.0:beta4:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.0.0:rc:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.0.0:rc2:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.0.1:*:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.0.1:pre:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.0.2:*:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.0.2:pre:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.0.3:*:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.0.4:rc1:*:*:*:*:*:*
- ghsa-coords2 versions
< 2.3.11+ 1 more
- (no CPE)range: < 2.3.11
- (no CPE)range: < 2.3.11
Patches
2abe97736b831Be sure to javascript_escape the email address to prevent apostrophes inadvertently causing javascript errors.
2 files changed · +6 −5
actionpack/lib/action_view/helpers/url_helper.rb+2 −1 modified@@ -471,7 +471,8 @@ def mail_to(email_address, name = nil, html_options = {}) email_address_obfuscated.gsub!(/\./, html_options.delete("replace_dot")) if html_options.has_key?("replace_dot") if encode == "javascript" - "document.write('#{content_tag("a", name || email_address_obfuscated.html_safe, html_options.merge({ "href" => "mailto:"+email_address+extras }))}');".each_byte do |c| + html = content_tag("a", name || email_address_obfuscated.html_safe, html_options.merge({ "href" => "mailto:"+html_escape(email_address)+extras })) + "document.write('#{escape_javascript(html)}');".each_byte do |c| string << sprintf("%%%x", c) end "<script type=\"#{Mime::JS}\">eval(decodeURIComponent('#{string}'))</script>"
actionpack/test/template/url_helper_test.rb+4 −4 modified@@ -333,11 +333,11 @@ def test_mail_to end def test_mail_to_with_javascript - assert_dom_equal "<script type=\"text/javascript\">eval(decodeURIComponent('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%22%3e%4d%79%20%65%6d%61%69%6c%3c%2f%61%3e%27%29%3b'))</script>", mail_to("me@domain.com", "My email", :encode => "javascript") + assert_dom_equal "<script type=\"text/javascript\">eval(decodeURIComponent('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%5c%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%5c%22%3e%4d%79%20%65%6d%61%69%6c%3c%5c%2f%61%3e%27%29%3b'))</script>", mail_to("me@domain.com", "My email", :encode => "javascript") end def test_mail_to_with_javascript_unicode - assert_dom_equal "<script type=\"text/javascript\">eval(decodeURIComponent('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%22%6d%61%69%6c%74%6f%3a%75%6e%69%63%6f%64%65%40%65%78%61%6d%70%6c%65%2e%63%6f%6d%22%3e%c3%ba%6e%69%63%6f%64%65%3c%2f%61%3e%27%29%3b'))</script>", mail_to("unicode@example.com", "únicode", :encode => "javascript") + assert_dom_equal "<script type=\"text/javascript\">eval(decodeURIComponent('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%5c%22%6d%61%69%6c%74%6f%3a%75%6e%69%63%6f%64%65%40%65%78%61%6d%70%6c%65%2e%63%6f%6d%5c%22%3e%c3%ba%6e%69%63%6f%64%65%3c%5c%2f%61%3e%27%29%3b'))</script>", mail_to("unicode@example.com", "únicode", :encode => "javascript") end def test_mail_with_options @@ -361,8 +361,8 @@ def test_mail_to_with_replace_options assert_dom_equal "<a href=\"mailto:%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d\">me(at)domain.com</a>", mail_to("me@domain.com", nil, :encode => "hex", :replace_at => "(at)") assert_dom_equal "<a href=\"mailto:%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d\">My email</a>", mail_to("me@domain.com", "My email", :encode => "hex", :replace_at => "(at)") assert_dom_equal "<a href=\"mailto:%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d\">me(at)domain(dot)com</a>", mail_to("me@domain.com", nil, :encode => "hex", :replace_at => "(at)", :replace_dot => "(dot)") - assert_dom_equal "<script type=\"text/javascript\">eval(decodeURIComponent('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%22%3e%4d%79%20%65%6d%61%69%6c%3c%2f%61%3e%27%29%3b'))</script>", mail_to("me@domain.com", "My email", :encode => "javascript", :replace_at => "(at)", :replace_dot => "(dot)") - assert_dom_equal "<script type=\"text/javascript\">eval(decodeURIComponent('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%22%3e%6d%65%28%61%74%29%64%6f%6d%61%69%6e%28%64%6f%74%29%63%6f%6d%3c%2f%61%3e%27%29%3b'))</script>", mail_to("me@domain.com", nil, :encode => "javascript", :replace_at => "(at)", :replace_dot => "(dot)") + assert_dom_equal "<script type=\"text/javascript\">eval(decodeURIComponent('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%5c%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%5c%22%3e%4d%79%20%65%6d%61%69%6c%3c%5c%2f%61%3e%27%29%3b'))</script>", mail_to("me@domain.com", "My email", :encode => "javascript", :replace_at => "(at)", :replace_dot => "(dot)") + assert_dom_equal "<script type=\"text/javascript\">eval(decodeURIComponent('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%5c%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%5c%22%3e%6d%65%28%61%74%29%64%6f%6d%61%69%6e%28%64%6f%74%29%63%6f%6d%3c%5c%2f%61%3e%27%29%3b'))</script>", mail_to("me@domain.com", nil, :encode => "javascript", :replace_at => "(at)", :replace_dot => "(dot)") end def protect_against_forgery?
e3dd2107c57aBe sure to javascript_escape the email address to prevent apostrophes inadvertently causing javascript errors.
2 files changed · +8 −5
actionpack/lib/action_view/helpers/url_helper.rb+3 −1 modified@@ -490,7 +490,9 @@ def mail_to(email_address, name = nil, html_options = {}) string = '' if encode == "javascript" - "document.write('#{content_tag("a", name || email_address_obfuscated.html_safe, html_options.merge("href" => "mailto:#{email_address}#{extras}".html_safe))}');".each_byte do |c| + html = content_tag("a", name || email_address_obfuscated.html_safe, html_options.merge("href" => "mailto:#{email_address}#{extras}".html_safe)) + html = escape_javascript(html) + "document.write('#{html}');".each_byte do |c| string << sprintf("%%%x", c) end "<script type=\"#{Mime::JS}\">eval(decodeURIComponent('#{string}'))</script>".html_safe
actionpack/test/template/url_helper_test.rb+5 −4 modified@@ -20,6 +20,7 @@ class UrlHelperTest < ActiveSupport::TestCase include routes.url_helpers include ActionView::Helpers::UrlHelper + include ActionView::Helpers::JavaScriptHelper include ActionDispatch::Assertions::DomAssertions include ActionView::Context include RenderERBUtils @@ -366,13 +367,13 @@ def test_mail_to def test_mail_to_with_javascript snippet = mail_to("me@domain.com", "My email", :encode => "javascript") - assert_dom_equal "<script type=\"text/javascript\">eval(decodeURIComponent('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%22%3e%4d%79%20%65%6d%61%69%6c%3c%2f%61%3e%27%29%3b'))</script>", snippet + assert_dom_equal "<script type=\"text/javascript\">eval(decodeURIComponent('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%5c%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%5c%22%3e%4d%79%20%65%6d%61%69%6c%3c%5c%2f%61%3e%27%29%3b'))</script>", snippet assert snippet.html_safe? end def test_mail_to_with_javascript_unicode snippet = mail_to("unicode@example.com", "únicode", :encode => "javascript") - assert_dom_equal "<script type=\"text/javascript\">eval(decodeURIComponent('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%22%6d%61%69%6c%74%6f%3a%75%6e%69%63%6f%64%65%40%65%78%61%6d%70%6c%65%2e%63%6f%6d%22%3e%c3%ba%6e%69%63%6f%64%65%3c%2f%61%3e%27%29%3b'))</script>", snippet + assert_dom_equal "<script type=\"text/javascript\">eval(decodeURIComponent('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%5c%22%6d%61%69%6c%74%6f%3a%75%6e%69%63%6f%64%65%40%65%78%61%6d%70%6c%65%2e%63%6f%6d%5c%22%3e%c3%ba%6e%69%63%6f%64%65%3c%5c%2f%61%3e%27%29%3b'))</script>", snippet assert snippet.html_safe end @@ -398,8 +399,8 @@ def test_mail_to_with_replace_options assert_dom_equal "<a href=\"mailto:%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d\">me(at)domain.com</a>", mail_to("me@domain.com", nil, :encode => "hex", :replace_at => "(at)") assert_dom_equal "<a href=\"mailto:%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d\">My email</a>", mail_to("me@domain.com", "My email", :encode => "hex", :replace_at => "(at)") assert_dom_equal "<a href=\"mailto:%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d\">me(at)domain(dot)com</a>", mail_to("me@domain.com", nil, :encode => "hex", :replace_at => "(at)", :replace_dot => "(dot)") - assert_dom_equal "<script type=\"text/javascript\">eval(decodeURIComponent('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%22%3e%4d%79%20%65%6d%61%69%6c%3c%2f%61%3e%27%29%3b'))</script>", mail_to("me@domain.com", "My email", :encode => "javascript", :replace_at => "(at)", :replace_dot => "(dot)") - assert_dom_equal "<script type=\"text/javascript\">eval(decodeURIComponent('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%22%3e%6d%65%28%61%74%29%64%6f%6d%61%69%6e%28%64%6f%74%29%63%6f%6d%3c%2f%61%3e%27%29%3b'))</script>", mail_to("me@domain.com", nil, :encode => "javascript", :replace_at => "(at)", :replace_dot => "(dot)") + assert_dom_equal "<script type=\"text/javascript\">eval(decodeURIComponent('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%5c%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%5c%22%3e%4d%79%20%65%6d%61%69%6c%3c%5c%2f%61%3e%27%29%3b'))</script>", mail_to("me@domain.com", "My email", :encode => "javascript", :replace_at => "(at)", :replace_dot => "(dot)") + assert_dom_equal "<script type=\"text/javascript\">eval(decodeURIComponent('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%5c%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%5c%22%3e%6d%65%28%61%74%29%64%6f%6d%61%69%6e%28%64%6f%74%29%63%6f%6d%3c%5c%2f%61%3e%27%29%3b'))</script>", mail_to("me@domain.com", nil, :encode => "javascript", :replace_at => "(at)", :replace_dot => "(dot)") end # TODO: button_to looks at this ... why?
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
22- groups.google.com/group/rubyonrails-security/msg/365b8a23b76a6b4anvdPatchWEB
- github.com/advisories/GHSA-75w6-p6mg-vh8jghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2011-0446ghsaADVISORY
- lists.fedoraproject.org/pipermail/package-announce/2011-April/057650.htmlnvdWEB
- lists.fedoraproject.org/pipermail/package-announce/2011-March/055074.htmlnvdWEB
- lists.fedoraproject.org/pipermail/package-announce/2011-March/055088.htmlnvdWEB
- www.debian.org/security/2011/dsa-2247nvdWEB
- github.com/rails/rails/commit/abe97736b8316f1b714cac56c115c0779aa73217ghsaWEB
- github.com/rails/rails/commit/e3dd2107c57a8efaaea5d61cf8da65f7444760b2ghsaWEB
- github.com/rubysec/ruby-advisory-db/blob/master/gems/actionpack/CVE-2011-0446.ymlghsaWEB
- github.com/rubysec/ruby-advisory-db/blob/master/gems/actionview/CVE-2011-0446.ymlghsaWEB
- groups.google.com/g/rubyonrails-security/c/8CpI7egxX4E/m/SmtqtyOKWzYJghsaWEB
- web.archive.org/web/20111225083933/http://secunia.com/advisories/43274ghsaWEB
- web.archive.org/web/20111225083933/http://secunia.com/advisories/43666ghsaWEB
- web.archive.org/web/20120527023027/http://www.securityfocus.com/bid/46291ghsaWEB
- web.archive.org/web/20200812054342/http://www.securitytracker.com/idghsaWEB
- secunia.com/advisories/43274nvd
- secunia.com/advisories/43666nvd
- www.securityfocus.com/bid/46291nvd
- www.securitytracker.com/idnvd
- www.vupen.com/english/advisories/2011/0587nvd
- www.vupen.com/english/advisories/2011/0877nvd
News mentions
0No linked articles in our index yet.