diff options
-rw-r--r-- | .changeset/smart-snakes-promise.md | 5 | ||||
-rw-r--r-- | packages/astro/src/runtime/server/render/server-islands.ts | 17 |
2 files changed, 18 insertions, 4 deletions
diff --git a/.changeset/smart-snakes-promise.md b/.changeset/smart-snakes-promise.md new file mode 100644 index 000000000..e46353e6a --- /dev/null +++ b/.changeset/smart-snakes-promise.md @@ -0,0 +1,5 @@ +--- +"astro": patch +--- + +Escapes HTML in serialized props diff --git a/packages/astro/src/runtime/server/render/server-islands.ts b/packages/astro/src/runtime/server/render/server-islands.ts index ee6b03ae2..52b6b006e 100644 --- a/packages/astro/src/runtime/server/render/server-islands.ts +++ b/packages/astro/src/runtime/server/render/server-islands.ts @@ -14,6 +14,15 @@ export function containsServerDirective(props: Record<string | number, any>) { return 'server:component-directive' in props; } +function safeJsonStringify(obj: any) { + return JSON.stringify(obj) + .replace(/\u2028/g, '\\u2028') + .replace(/\u2029/g, '\\u2029') + .replace(/</g, '\\u003c') + .replace(/>/g, '\\u003e') + .replace(/\//g, '\\u002f'); +} + export function renderServerIsland( result: SSRResult, _displayName: string, @@ -53,13 +62,13 @@ export function renderServerIsland( const hostId = crypto.randomUUID(); destination.write(`<script async type="module" data-island-id="${hostId}"> -let componentId = ${JSON.stringify(componentId)}; -let componentExport = ${JSON.stringify(componentExport)}; +let componentId = ${safeJsonStringify(componentId)}; +let componentExport = ${safeJsonStringify(componentExport)}; let script = document.querySelector('script[data-island-id="${hostId}"]'); let data = { componentExport, - props: ${JSON.stringify(props)}, - slots: ${JSON.stringify(renderedSlots)}, + props: ${safeJsonStringify(props)}, + slots: ${safeJsonStringify(renderedSlots)}, }; let response = await fetch('/_server-islands/${componentId}', { |