diff --git a/.changeset/fix-that-thing.md b/.changeset/fix-that-thing.md new file mode 100644 index 0000000000..aa32c4dce8 --- /dev/null +++ b/.changeset/fix-that-thing.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: always escape option body in SSR \ No newline at end of file diff --git a/packages/svelte/src/internal/server/renderer.js b/packages/svelte/src/internal/server/renderer.js index 9df914b35a..7f9a922f33 100644 --- a/packages/svelte/src/internal/server/renderer.js +++ b/packages/svelte/src/internal/server/renderer.js @@ -12,6 +12,7 @@ import { get_render_context, with_render_context, init_render_context } from './ import { sha256 } from './crypto.js'; import * as devalue from 'devalue'; import { noop } from '../shared/utils.js'; +import { escape_html } from '../../escaping.js'; /** @typedef {'head' | 'body'} RendererType */ /** @typedef {{ [key in RendererType]: string }} AccumulatedContent */ @@ -275,7 +276,7 @@ export class Renderer { renderer.#out.push(' selected=""'); } - renderer.#out.push(`>${body}${is_rich ? '' : ''}`); + renderer.#out.push(`>${escape_html(body)}${is_rich ? '' : ''}`); // super edge case, but may as well handle it if (head) { diff --git a/packages/svelte/tests/server-side-rendering/samples/option-body-escaped/_expected.html b/packages/svelte/tests/server-side-rendering/samples/option-body-escaped/_expected.html new file mode 100644 index 0000000000..f1f609d095 --- /dev/null +++ b/packages/svelte/tests/server-side-rendering/samples/option-body-escaped/_expected.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/svelte/tests/server-side-rendering/samples/option-body-escaped/main.svelte b/packages/svelte/tests/server-side-rendering/samples/option-body-escaped/main.svelte new file mode 100644 index 0000000000..ab28f8bda5 --- /dev/null +++ b/packages/svelte/tests/server-side-rendering/samples/option-body-escaped/main.svelte @@ -0,0 +1,6 @@ + +