diff --git a/spec/blueprint/html/attributes_handling_spec.cr b/spec/blueprint/html/attributes_handling_spec.cr index 983bd6a..c92b5c4 100644 --- a/spec/blueprint/html/attributes_handling_spec.cr +++ b/spec/blueprint/html/attributes_handling_spec.cr @@ -114,4 +114,36 @@ describe "attributes handling" do actual_html.should eq expected_html end + + it "raises error if attribute names include unsafe characters" do + # Hash + {% for character in ["<", ">", "&", %("), "'"] %} + expect_raises(Blueprint::HTML::ArgumentError, %(Unsafe attribute name: `attr-{{character.id}}`)) do + Blueprint::HTML.build do + div({ %(attr-{{character.id}}) => "some value"}) do + "Blueprint" + end + end + end + {% end %} + + # NamedTuple + {% for character in ["<", ">", "&", "'"] %} + expect_raises(Blueprint::HTML::ArgumentError, %(Unsafe attribute name: `attr-{{character.id}}`)) do + Blueprint::HTML.build do + div("attr-{{character.id}}": "some value") do + "Blueprint" + end + end + end + {% end %} + + expect_raises(Blueprint::HTML::ArgumentError, %(Unsafe attribute name: `attr-"`)) do + Blueprint::HTML.build do + div("attr-\"": "some value") do + "Blueprint" + end + end + end + end end diff --git a/src/blueprint/html/attributes_renderer.cr b/src/blueprint/html/attributes_renderer.cr index 172dfb2..1477493 100644 --- a/src/blueprint/html/attributes_renderer.cr +++ b/src/blueprint/html/attributes_renderer.cr @@ -76,11 +76,15 @@ module Blueprint::HTML::AttributesRenderer append_value buffer, value.to_s end - private def parse_name(name : Symbol) : String - name.to_s.gsub("_", "-") - end - private def parse_name(name : String) : String + if name.matches?(/[<>&"']/) + raise Blueprint::HTML::ArgumentError.new("Unsafe attribute name: `#{name}`") + end + name end + + private def parse_name(name : Symbol) : String + parse_name(name.to_s.gsub("_", "-")) + end end diff --git a/src/blueprint/html/errors.cr b/src/blueprint/html/errors.cr new file mode 100644 index 0000000..af51ff0 --- /dev/null +++ b/src/blueprint/html/errors.cr @@ -0,0 +1,2 @@ +class Blueprint::HTML::ArgumentError < ArgumentError +end