[fix] harden attribute escaping during ssr (#7530)

pull/7641/head
Maurício Kishi 2 years ago committed by GitHub
parent 9635a2e413
commit f8605d6acb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -85,18 +85,20 @@ export function escape(value: unknown, is_attr = false) {
let escaped = ''; let escaped = '';
let last = 0; let last = 0;
while (pattern.test(str)) { while (pattern.test(str)) {
const i = pattern.lastIndex - 1; const i = pattern.lastIndex - 1;
const ch = str[i]; const ch = str[i];
escaped += str.substring(last, i) + (ch === '&' ? '&' : (ch === '"' ? '"' : '<')); escaped += str.substring(last, i) + (ch === '&' ? '&' : (ch === '"' ? '"' : '<'));
last = i + 1; last = i + 1;
} }
return escaped + str.substring(last); return escaped + str.substring(last);
} }
export function escape_attribute_value(value) { 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) { export function escape_object(obj) {
@ -192,7 +194,7 @@ export function create_ssr_component(fn) {
export function add_attribute(name, value, boolean) { export function add_attribute(name, value, boolean) {
if (value == null || (boolean && !value)) return ''; 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}`; return ` ${name}${assignment}`;
} }

@ -2,4 +2,10 @@
bar="'></div><script>alert(42)</script>" bar="'></div><script>alert(42)</script>"
foo="&quot;></div><script>alert(42)</script>" foo="&quot;></div><script>alert(42)</script>"
qux="&amp;&amp;&amp;" 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> <script>
const safe = { foo: 'foo' };
const unsafe = { toString: () => '"><script>alert(42)<\/script>' };
export let props = { export let props = {
foo: '"></div><script>alert(42)</' + 'script>', foo: '"></div><script>alert(42)</' + 'script>',
bar: "'></div><script>alert(42)</" + 'script>', bar: "'></div><script>alert(42)</" + 'script>',
['"></div><script>alert(42)</' + 'script>']: 'baz', ['"></div><script>alert(42)</' + 'script>']: 'baz',
qux: '&&&', qux: '&&&',
quux: unsafe
}; };
</script> </script>
<div {...props}></div> <div {...props}></div>
<div {...safe} {unsafe}></div>

Loading…
Cancel
Save