diff --git a/packages/vinext/src/shims/navigation.ts b/packages/vinext/src/shims/navigation.ts index a396d885..1b935b70 100644 --- a/packages/vinext/src/shims/navigation.ts +++ b/packages/vinext/src/shims/navigation.ts @@ -336,10 +336,10 @@ export function useParams< } /** - * Check if a href is an external URL (any URL scheme per RFC 3986, or protocol-relative). + * Check if a href is an external URL (http/https, or protocol-relative). */ function isExternalUrl(href: string): boolean { - return /^[a-z][a-z0-9+.-]*:/i.test(href) || href.startsWith("//"); + return /^https?:\/\//i.test(href) || href.startsWith("//"); } /** diff --git a/packages/vinext/src/shims/router.ts b/packages/vinext/src/shims/router.ts index f4912c4f..c855adc9 100644 --- a/packages/vinext/src/shims/router.ts +++ b/packages/vinext/src/shims/router.ts @@ -132,9 +132,9 @@ export function applyNavigationLocale(url: string, locale?: string): string { return `/${locale}${url.startsWith("/") ? url : `/${url}`}`; } -/** Check if a URL is external (any URL scheme per RFC 3986, or protocol-relative) */ +/** Check if a URL is external (http/https, or protocol-relative) */ export function isExternalUrl(url: string): boolean { - return /^[a-z][a-z0-9+.-]*:/i.test(url) || url.startsWith("//"); + return /^https?:\/\//i.test(url) || url.startsWith("//"); } /** Check if a href is only a hash change relative to the current URL */ diff --git a/tests/link.test.ts b/tests/link.test.ts index 93461149..3aac3a49 100644 --- a/tests/link.test.ts +++ b/tests/link.test.ts @@ -191,6 +191,12 @@ describe("isExternalUrl", () => { it("hash-only is not external", () => { expect(isExternalUrl("#section")).toBe(false); }); + + it("blocks dangerous schemes from being treated as external", () => { + expect(isExternalUrl("javascript:alert(1)")).toBe(false); + expect(isExternalUrl("data:text/html,

x

")).toBe(false); + }); + }); // ─── isHashOnlyChange ─────────────────────────────────────────────────── diff --git a/tests/shims.test.ts b/tests/shims.test.ts index bafb1fc2..3b86aaec 100644 --- a/tests/shims.test.ts +++ b/tests/shims.test.ts @@ -5528,6 +5528,12 @@ describe("Pages Router router helpers", () => { it("returns false for query-only", () => { expect(isExternalUrl("?foo=1")).toBe(false); }); + + it("returns false for dangerous schemes", () => { + expect(isExternalUrl("javascript:alert(1)")).toBe(false); + expect(isExternalUrl("data:text/html,

x

")).toBe(false); + }); + }); describe("isHashOnlyChange", () => {