Skip to content

Commit

Permalink
[fix] harden attribute escaping during ssr (#7530)
Browse files Browse the repository at this point in the history
  • Loading branch information
mrkishi committed Jun 20, 2022
1 parent 9635a2e commit f8605d6
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 10 deletions.
18 changes: 10 additions & 8 deletions src/runtime/internal/ssr.ts
Expand Up @@ -85,18 +85,20 @@ export function escape(value: unknown, is_attr = false) {
let escaped = '';
let last = 0;

while (pattern.test(str)) {
const i = pattern.lastIndex - 1;
const ch = str[i];
escaped += str.substring(last, i) + (ch === '&' ? '&' : (ch === '"' ? '"' : '<'));
last = i + 1;
}
while (pattern.test(str)) {
const i = pattern.lastIndex - 1;
const ch = str[i];
escaped += str.substring(last, i) + (ch === '&' ? '&' : (ch === '"' ? '"' : '<'));
last = i + 1;
}

return escaped + str.substring(last);
}

export function escape_attribute_value(value) {
return typeof value === 'string' ? escape(value, true) : value;
// keep booleans, null, and undefined for the sake of `spread`
const should_escape = typeof value === 'string' || (value && typeof value === 'object');
return should_escape ? escape(value, true) : value;
}

export function escape_object(obj) {
Expand Down Expand Up @@ -192,7 +194,7 @@ export function create_ssr_component(fn) {

export function add_attribute(name, value, boolean) {
if (value == null || (boolean && !value)) return '';
const assignment = (boolean && value === true) ? '' : `="${escape_attribute_value(value.toString())}"`;
const assignment = (boolean && value === true) ? '' : `="${escape(value, true)}"`;
return ` ${name}${assignment}`;
}

Expand Down
Expand Up @@ -2,4 +2,10 @@
bar="'></div><script>alert(42)</script>"
foo="&quot;></div><script>alert(42)</script>"
qux="&amp;&amp;&amp;"
></div>
quux="&quot;><script>alert(42)</script>"
></div>

<div
foo="foo"
unsafe="&quot;><script>alert(42)</script>"
></div>
@@ -1,10 +1,15 @@
<script>
const safe = { foo: 'foo' };
const unsafe = { toString: () => '"><script>alert(42)<\/script>' };
export let props = {
foo: '"></div><script>alert(42)</' + 'script>',
bar: "'></div><script>alert(42)</" + 'script>',
['"></div><script>alert(42)</' + 'script>']: 'baz',
qux: '&&&',
quux: unsafe
};
</script>

<div {...props}></div>
<div {...props}></div>
<div {...safe} {unsafe}></div>

0 comments on commit f8605d6

Please sign in to comment.