diff --git a/.changeset/moody-carrots-lay.md b/.changeset/moody-carrots-lay.md new file mode 100644 index 0000000000..e10729bc60 --- /dev/null +++ b/.changeset/moody-carrots-lay.md @@ -0,0 +1,5 @@ +--- +"svelte": patch +--- + +fix: don't execute scripts inside `@html` when instantiated on the client diff --git a/packages/svelte/src/internal/client/reconciler.js b/packages/svelte/src/internal/client/reconciler.js index 7f0aa36a33..0e74b33af6 100644 --- a/packages/svelte/src/internal/client/reconciler.js +++ b/packages/svelte/src/internal/client/reconciler.js @@ -103,7 +103,9 @@ export function reconcile_html(target, value, svg) { if (svg) { html = ``; } - var content = create_fragment_with_script_from_html(html); + // Don't use create_fragment_with_script_from_html here because that would mean script tags are executed. + // @html is basically `.innerHTML = ...` and that doesn't execute scripts either due to security reasons. + var content = create_fragment_from_html(html); if (svg) { content = /** @type {DocumentFragment} */ (/** @type {unknown} */ (content.firstChild)); } diff --git a/packages/svelte/tests/runtime-browser/samples/html-tag-script/_config.js b/packages/svelte/tests/runtime-browser/samples/html-tag-script/_config.js new file mode 100644 index 0000000000..d9cab08587 --- /dev/null +++ b/packages/svelte/tests/runtime-browser/samples/html-tag-script/_config.js @@ -0,0 +1,9 @@ +import { test } from '../../assert'; + +export default test({ + // Test that @html does not execute scripts when instantiated in the client. + // Needs to be in this test suite because JSDOM does not quite get this right. + html: `
`, + skip_if_ssr: 'permanent', + skip_if_hydrate: 'permanent' +}); diff --git a/packages/svelte/tests/runtime-browser/samples/html-tag-script/main.svelte b/packages/svelte/tests/runtime-browser/samples/html-tag-script/main.svelte new file mode 100644 index 0000000000..9a3a6fe6da --- /dev/null +++ b/packages/svelte/tests/runtime-browser/samples/html-tag-script/main.svelte @@ -0,0 +1,2 @@ + +{@html ``}