diff --git a/lib/phlex/sgml.rb b/lib/phlex/sgml.rb index c76cf547..653bf1d3 100644 --- a/lib/phlex/sgml.rb +++ b/lib/phlex/sgml.rb @@ -393,14 +393,6 @@ def __final_attributes__(**attributes) attributes = process_attributes(**attributes) end - if attributes[:href]&.start_with?(/\s*javascript:/) - attributes.delete(:href) - end - - if attributes["href"]&.start_with?(/\s*javascript:/) - attributes.delete("href") - end - buffer = +"" __build_attributes__(attributes, buffer: buffer) @@ -418,8 +410,11 @@ def __build_attributes__(attributes, buffer:) else raise ArgumentError, "Attribute keys should be Strings or Symbols." end + lower_name = name.downcase + next if lower_name == "href" && v.start_with?(/\s*javascript:/i) + # Detect unsafe attribute names. Attribute names are considered unsafe if they match an event attribute or include unsafe characters. - if HTML::EVENT_ATTRIBUTES[name] || name.match?(/[<>&"']/) + if HTML::EVENT_ATTRIBUTES[lower_name] || name.match?(/[<>&"']/) raise ArgumentError, "Unsafe attribute name detected: #{k}." end diff --git a/test/phlex/view/naughty_business.rb b/test/phlex/view/naughty_business.rb index 5e4cad47..c75dcff0 100644 --- a/test/phlex/view/naughty_business.rb +++ b/test/phlex/view/naughty_business.rb @@ -3,6 +3,36 @@ describe Phlex::HTML do extend ViewHelper + with "naughty javascript links" do + view do + def template + a(href: "javascript:alert(1)") { "a" } + a(href: "JAVASCRIPT:alert(1)") { "b" } + a(href: :"JAVASCRIPT:alert(1)") { "c" } + a(HREF: "javascript:alert(1)") { "d" } + end + end + + it "removes the href attributes" do + expect(output).to be == "abcd" + end + end + + with "naughty uppercase event tag" do + view do + def template + button ONCLICK: "ALERT(1)" do + "naughty button" + end + end + end + + it "raises" do + expect { output }.to raise_exception ArgumentError, + message: be == "Unsafe attribute name detected: ONCLICK." + end + end + with "naughty text" do view do def view_template