diff --git a/specs/experimental/switch_locale_path_link_ssr.spec.ts b/specs/experimental/switch_locale_path_link_ssr.spec.ts index e43de3883..881c315b2 100644 --- a/specs/experimental/switch_locale_path_link_ssr.spec.ts +++ b/specs/experimental/switch_locale_path_link_ssr.spec.ts @@ -55,4 +55,14 @@ describe('experimental.switchLocalePathLinkSSR', async () => { expect(product2dom.querySelector('#i18n-alt-en').href).toEqual('/products/red-mug') expect(product2dom.querySelector('#switch-locale-path-link-en').href).toEqual('/products/red-mug') }) + + test('encode localized path to prevent XSS', async () => { + const url = `/experimental//"><` + + const html = await $fetch(url) + const dom = getDom(html) + + // the localized should be the same as encoded + expect(dom.querySelector('#slp-xss a').href).toEqual(encodeURI('/nl' + url)) + }) }) diff --git a/specs/fixtures/basic_usage/pages/experimental/[...slug].vue b/specs/fixtures/basic_usage/pages/experimental/[...slug].vue new file mode 100644 index 000000000..5c550a091 --- /dev/null +++ b/specs/fixtures/basic_usage/pages/experimental/[...slug].vue @@ -0,0 +1,8 @@ + + + diff --git a/src/runtime/components/SwitchLocalePathLink.ts b/src/runtime/components/SwitchLocalePathLink.ts index 906a04fbd..3166d0cce 100644 --- a/src/runtime/components/SwitchLocalePathLink.ts +++ b/src/runtime/components/SwitchLocalePathLink.ts @@ -21,7 +21,7 @@ export default defineComponent({ return () => [ h(Comment, `${SWITCH_LOCALE_PATH_LINK_IDENTIFIER}-[${props.locale}]`), - h(NuxtLink, { ...attrs, to: switchLocalePath(props.locale) }, slots.default), + h(NuxtLink, { ...attrs, to: encodeURI(switchLocalePath(props.locale)) }, slots.default), h(Comment, `/${SWITCH_LOCALE_PATH_LINK_IDENTIFIER}`) ] } diff --git a/src/runtime/plugins/switch-locale-path-ssr.ts b/src/runtime/plugins/switch-locale-path-ssr.ts index 87d3911d2..598665889 100644 --- a/src/runtime/plugins/switch-locale-path-ssr.ts +++ b/src/runtime/plugins/switch-locale-path-ssr.ts @@ -25,7 +25,8 @@ export default defineNuxtPlugin({ ctx.renderResult.html = ctx.renderResult.html.replaceAll( switchLocalePathLinkWrapperExpr, - (match: string, p1: string) => match.replace(/href="([^"]+)"/, `href="${switchLocalePath(p1 ?? '')}"`) + (match: string, p1: string) => + match.replace(/href="([^"]+)"/, `href="${encodeURI(switchLocalePath(p1 ?? ''))}"`) ) }) }