aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbgw <29340584+bgwdotdev@users.noreply.github.com>2024-04-25 19:19:15 +0100
committerGitHub <noreply@github.com>2024-04-25 19:19:15 +0100
commit93aeeb7a6316389f3bd4bbdb7a9ffc555677e719 (patch)
tree70d2443bf31090a320c56b1029d99c0c4bb05dd6
parent06b75022eed1e8bbed13a85cc8aeb18199040392 (diff)
downloadlustre-93aeeb7a6316389f3bd4bbdb7a9ffc555677e719.tar.gz
lustre-93aeeb7a6316389f3bd4bbdb7a9ffc555677e719.zip
🔀 Escape attribute values when emitting static HTML. (#113)
* fix: add the escape function over custom attribute values * fix: update class and style attribute values to be escaped
-rw-r--r--birdie_snapshots/can_safely_escape_dangerous_symbols_in_attributes.accepted5
-rw-r--r--src/lustre/internals/vdom.gleam33
-rw-r--r--test/apps/static.gleam15
-rw-r--r--test/lustre_test.gleam6
4 files changed, 52 insertions, 7 deletions
diff --git a/birdie_snapshots/can_safely_escape_dangerous_symbols_in_attributes.accepted b/birdie_snapshots/can_safely_escape_dangerous_symbols_in_attributes.accepted
new file mode 100644
index 0000000..cbb7f9d
--- /dev/null
+++ b/birdie_snapshots/can_safely_escape_dangerous_symbols_in_attributes.accepted
@@ -0,0 +1,5 @@
+---
+version: 1.1.2
+title: Can safely escape dangerous symbols in attributes
+---
+<div example="{&quot;mykey&quot;: &quot;myvalue&quot;}" class="&#39;badquotes&#39;" style="background:&quot;&gt;&lt;script&gt;alert`1`&lt;/script&gt;;"></div> \ No newline at end of file
diff --git a/src/lustre/internals/vdom.gleam b/src/lustre/internals/vdom.gleam
index fc4a4a3..4930f80 100644
--- a/src/lustre/internals/vdom.gleam
+++ b/src/lustre/internals/vdom.gleam
@@ -282,10 +282,30 @@ fn attributes_to_string_builder(
style,
inner_html <> val,
)
- Ok(#("class", val)) if class == "" -> #(html, val, style, inner_html)
- Ok(#("class", val)) -> #(html, class <> " " <> val, style, inner_html)
- Ok(#("style", val)) if style == "" -> #(html, class, val, inner_html)
- Ok(#("style", val)) -> #(html, class, style <> " " <> val, inner_html)
+ Ok(#("class", val)) if class == "" -> #(
+ html,
+ escape("", val),
+ style,
+ inner_html,
+ )
+ Ok(#("class", val)) -> #(
+ html,
+ class <> " " <> escape("", val),
+ style,
+ inner_html,
+ )
+ Ok(#("style", val)) if style == "" -> #(
+ html,
+ class,
+ escape("", val),
+ inner_html,
+ )
+ Ok(#("style", val)) -> #(
+ html,
+ class,
+ style <> " " <> escape("", val),
+ inner_html,
+ )
Ok(#(key, "")) -> #(
string_builder.append(html, " " <> key),
class,
@@ -293,7 +313,10 @@ fn attributes_to_string_builder(
inner_html,
)
Ok(#(key, val)) -> #(
- string_builder.append(html, " " <> key <> "=\"" <> val <> "\""),
+ string_builder.append(
+ html,
+ " " <> key <> "=\"" <> escape("", val) <> "\"",
+ ),
class,
style,
inner_html,
diff --git a/test/apps/static.gleam b/test/apps/static.gleam
index 5c6ca05..fcf52f3 100644
--- a/test/apps/static.gleam
+++ b/test/apps/static.gleam
@@ -1,8 +1,8 @@
// IMPORTS ---------------------------------------------------------------------
-import lustre/attribute.{disabled, src}
+import lustre/attribute.{attribute, class, disabled, src, style}
import lustre/element.{text}
-import lustre/element/html.{body, h1, head, html, img, input, title}
+import lustre/element/html.{body, div, h1, head, html, img, input, title}
// VIEW ------------------------------------------------------------------------
@@ -16,3 +16,14 @@ pub fn view() {
]),
])
}
+
+pub fn escaped_attribute() {
+ div(
+ [
+ class("'badquotes'"),
+ style([#("background", "\"><script>alert`1`</script>")]),
+ attribute("example", "{\"mykey\": \"myvalue\"}"),
+ ],
+ [],
+ )
+}
diff --git a/test/lustre_test.gleam b/test/lustre_test.gleam
index f3a2993..6cd93c3 100644
--- a/test/lustre_test.gleam
+++ b/test/lustre_test.gleam
@@ -149,3 +149,9 @@ pub fn fragment_counter_diff_test() {
birdie.snap(json.to_string(patch.element_diff_to_json(diff)), title)
process.send(runtime, Shutdown)
}
+
+pub fn escaped_attribute_test() {
+ let title = "Can safely escape dangerous symbols in attributes"
+ let el = static.escaped_attribute()
+ birdie.snap(element.to_string(el), title)
+}