CVE-2024-32463
Description
phlex is an open source framework for building object-oriented views in Ruby. There is a potential cross-site scripting (XSS) vulnerability that can be exploited via maliciously crafted user data. The filter to detect and prevent the use of the javascript: URL scheme in the href attribute of an <a> tag could be bypassed with tab \t or newline \n characters between the characters of the protocol, e.g. java\tscript:. This vulnerability is fixed in 1.10.1, 1.9.2, 1.8.3, 1.7.2, 1.6.3, 1.5.3, and 1.4.2. Configuring a Content Security Policy that does not allow unsafe-inline would effectively prevent this vulnerability from being exploited.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
phlexRubyGems | >= 1.10.0, < 1.10.1 | 1.10.1 |
phlexRubyGems | >= 1.9.0, < 1.9.2 | 1.9.2 |
phlexRubyGems | >= 1.8.0, < 1.8.3 | 1.8.3 |
phlexRubyGems | >= 1.7.0, < 1.7.2 | 1.7.2 |
phlexRubyGems | >= 1.6.0, < 1.6.3 | 1.6.3 |
phlexRubyGems | >= 1.5.0, < 1.5.3 | 1.5.3 |
phlexRubyGems | < 1.4.2 | 1.4.2 |
Patches
961c03034c8c8169dfbfb803a57f2982a2e337d53c220878f1c9f72a0ab5b175f67a4cd11c4056b48f2f49e3f5b9806552 files changed · +73 −1
lib/phlex/sgml.rb+1 −1 modified@@ -382,7 +382,7 @@ def __attributes__(attributes, buffer = +"") end lower_name = name.downcase - next if lower_name == "href" && v.start_with?(/\s*javascript:/i) + next if lower_name == "href" && v.to_s.downcase.tr("\t \n", "").start_with?("javascript:") # Detect unsafe attribute names. Attribute names are considered unsafe if they match an event attribute or include unsafe characters. if HTML::EVENT_ATTRIBUTES.include?(lower_name) || name.match?(/[<>&"']/)
test/phlex/view/naughty_business.rb+72 −0 modified@@ -85,6 +85,78 @@ def view_template end end + with "naughty javascript link protocol with a hidden tab character" do + view do + def view_template + a(href: "\tjavascript:alert(1)") { "XSS" } + a(href: "j\tavascript:alert(1)") { "XSS" } + a(href: "ja\tvascript:alert(1)") { "XSS" } + a(href: "jav\tascript:alert(1)") { "XSS" } + a(href: "java\tscript:alert(1)") { "XSS" } + a(href: "javas\tcript:alert(1)") { "XSS" } + a(href: "javasc\tript:alert(1)") { "XSS" } + a(href: "javascr\tipt:alert(1)") { "XSS" } + a(href: "javascri\tpt:alert(1)") { "XSS" } + a(href: "javascrip\tt:alert(1)") { "XSS" } + a(href: "javascript\t:alert(1)") { "XSS" } + a(href: "javascript:\talert(1)") { "XSS" } + end + end + + it "strips the javascript protocol" do + expect(output.scan("<a>").size).to be == 12 + expect(output.scan("href").size).to be == 0 + end + end + + with "naughty javascript link protocol with a hidden newline character" do + view do + def view_template + a(href: "\njavascript:alert(1)") { "XSS" } + a(href: "j\navascript:alert(1)") { "XSS" } + a(href: "ja\nvascript:alert(1)") { "XSS" } + a(href: "jav\nascript:alert(1)") { "XSS" } + a(href: "java\nscript:alert(1)") { "XSS" } + a(href: "javas\ncript:alert(1)") { "XSS" } + a(href: "javasc\nript:alert(1)") { "XSS" } + a(href: "javascr\nipt:alert(1)") { "XSS" } + a(href: "javascri\npt:alert(1)") { "XSS" } + a(href: "javascrip\nt:alert(1)") { "XSS" } + a(href: "javascript\n:alert(1)") { "XSS" } + a(href: "javascript:\nalert(1)") { "XSS" } + end + end + + it "strips the javascript protocol" do + expect(output.scan("<a>").size).to be == 12 + expect(output.scan("href").size).to be == 0 + end + end + + with "naughty javascript link protocol with a hidden whitespace character" do + view do + def view_template + a(href: " javascript:alert(1)") { "XSS" } + a(href: "j avascript:alert(1)") { "XSS" } + a(href: "ja vascript:alert(1)") { "XSS" } + a(href: "jav ascript:alert(1)") { "XSS" } + a(href: "java script:alert(1)") { "XSS" } + a(href: "javas cript:alert(1)") { "XSS" } + a(href: "javasc ript:alert(1)") { "XSS" } + a(href: "javascr ipt:alert(1)") { "XSS" } + a(href: "javascri pt:alert(1)") { "XSS" } + a(href: "javascrip t:alert(1)") { "XSS" } + a(href: "javascript :alert(1)") { "XSS" } + a(href: "javascript: alert(1)") { "XSS" } + end + end + + it "strips the javascript protocol" do + expect(output.scan("<a>").size).to be == 12 + expect(output.scan("href").size).to be == 0 + end + end + Phlex::HTML::EVENT_ATTRIBUTES.each do |event_attribute| with "with naughty #{event_attribute} attribute" do naughty_attributes = { event_attribute => "alert(1);" }
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
7- github.com/advisories/GHSA-g7xq-xv8c-h98cghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2024-32463ghsaADVISORY
- developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-PolicynvdWEB
- developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-PolicynvdWEB
- github.com/phlex-ruby/phlex/commit/9e3f5b980655817993682e409cbda72956d865cbnvdWEB
- github.com/phlex-ruby/phlex/security/advisories/GHSA-g7xq-xv8c-h98cnvdWEB
- github.com/rubysec/ruby-advisory-db/blob/master/gems/phlex/CVE-2024-32463.ymlghsaWEB
News mentions
0No linked articles in our index yet.