Skip to content

Commit 62a0139

Browse files
committed
Make sure class={@value} in HEEx is escaped
1 parent b7cf6da commit 62a0139

File tree

2 files changed

+20
-12
lines changed

2 files changed

+20
-12
lines changed

lib/phoenix_html/tag.ex

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,15 @@ defmodule Phoenix.HTML.Tag do
127127
{:safe, attrs |> Enum.to_list() |> build_attrs()}
128128
end
129129

130+
defp build_attrs([{k, true} | t]),
131+
do: [?\s, key_escape(k) | build_attrs(t)]
132+
133+
defp build_attrs([{_, false} | t]),
134+
do: build_attrs(t)
135+
136+
defp build_attrs([{_, nil} | t]),
137+
do: build_attrs(t)
138+
130139
defp build_attrs([{"data", v} | t]) when is_list(v),
131140
do: nested_attrs(v, " data", t)
132141

@@ -145,15 +154,6 @@ defmodule Phoenix.HTML.Tag do
145154
defp build_attrs([{:class, v} | t]) when is_list(v),
146155
do: [" class=\"", class_value(v), ?" | build_attrs(t)]
147156

148-
defp build_attrs([{k, true} | t]),
149-
do: [?\s, key_escape(k) | build_attrs(t)]
150-
151-
defp build_attrs([{_, false} | t]),
152-
do: build_attrs(t)
153-
154-
defp build_attrs([{_, nil} | t]),
155-
do: build_attrs(t)
156-
157157
defp build_attrs([{k, v} | t]),
158158
do: [?\s, key_escape(k), ?=, ?", attr_escape(v), ?" | build_attrs(t)]
159159

@@ -172,10 +172,11 @@ defmodule Phoenix.HTML.Tag do
172172
value
173173
|> Enum.filter(& &1)
174174
|> Enum.join(" ")
175+
|> attr_escape()
175176
end
176177

177178
defp class_value(value) do
178-
value
179+
attr_escape(value)
179180
end
180181

181182
defp key_escape(value) when is_atom(value), do: String.replace(Atom.to_string(value), "_", "-")

test/phoenix_html/tag_test.exs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,18 @@ defmodule Phoenix.HTML.TagTest do
3939

4040
test "handle class value as string" do
4141
assert attributes_escape([{:class, "btn"}]) |> safe_to_string() == ~s( class="btn")
42+
assert attributes_escape([{:class, "<active>"}]) |> safe_to_string() == ~s( class="&lt;active&gt;")
4243
end
4344

4445
test "handle class value as list" do
45-
assert attributes_escape([{:class, ["btn", nil, false, "active"]}]) |> safe_to_string() ==
46-
~s( class="btn active")
46+
assert attributes_escape([{:class, ["btn", nil, false, "<active>"]}]) |> safe_to_string() ==
47+
~s( class="btn &lt;active&gt;")
48+
end
49+
50+
test "handle class value as false/nil/true" do
51+
assert attributes_escape([{:class, false}]) |> safe_to_string() == ~s()
52+
assert attributes_escape([{:class, nil}]) |> safe_to_string() == ~s()
53+
assert attributes_escape([{:class, true}]) |> safe_to_string() == ~s( class)
4754
end
4855

4956
test "handle class key as string" do

0 commit comments

Comments
 (0)