Skip to content

Commit 0df5abc

Browse files
Merge commit from fork
* fix: escape `innerText` and `textContent` bindings of `contenteditable` * fix: better if else structure
1 parent 0298e97 commit 0df5abc

File tree

4 files changed

+19
-2
lines changed

4 files changed

+19
-2
lines changed

.changeset/bindings-xss-fix.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
fix: escape `innerText` and `textContent` bindings of `contenteditable`

packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/element.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,13 @@ export function build_element_attributes(node, context, transform) {
123123

124124
expression = transform(expression, attribute.metadata.expression);
125125

126-
if (is_content_editable_binding(attribute.name)) {
126+
if (attribute.name === 'innerHTML') {
127+
// innerHTML is the only binding we don't escape
127128
content = expression;
128-
} else if (attribute.name === 'value' && node.name === 'textarea') {
129+
} else if (
130+
is_content_editable_binding(attribute.name) ||
131+
(attribute.name === 'value' && node.name === 'textarea')
132+
) {
129133
content = b.call('$.escape', expression);
130134
} else if (attribute.name === 'group' && attribute.expression.type !== 'SequenceExpression') {
131135
const value_attribute = /** @type {AST.Attribute | undefined} */ (
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<!--[--><div contenteditable="">&lt;script>alert('pwnd')&lt;/script></div> <div contenteditable="">&lt;script>alert('pwnd')&lt;/script></div> <div contenteditable=""><script>alert('pwnd')</script></div><!--]-->
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<script>
2+
let data = $state("<scri"+"pt>alert('pwnd')</scr"+"ipt>");
3+
</script>
4+
5+
<div contenteditable bind:innerText={data}></div>
6+
<div contenteditable bind:textContent={data}></div>
7+
<div contenteditable bind:innerHTML={data}></div>

0 commit comments

Comments
 (0)