diff --git a/components/dashboard/src/utils.test.ts b/components/dashboard/src/utils.test.ts index 6de77f411f7b6c..2dad4bf8fa6d6e 100644 --- a/components/dashboard/src/utils.test.ts +++ b/components/dashboard/src/utils.test.ts @@ -45,6 +45,12 @@ test("urlHash and isTrustedUrlOrPath", () => { { location: "/", trusted: true }, // eslint-disable-next-line no-script-url { location: "javascript:alert(1)", trusted: false }, + // XSS bypass attempt with javascript: protocol and matching hostname + // eslint-disable-next-line no-script-url + { location: "javascript://example.org/%250aalert(1)", trusted: false }, + // Other protocol attempts + { location: "data:text/html,", trusted: false }, + { location: "vbscript:alert(1)", trusted: false }, ]; isTrustedUrlOrPathCases.forEach(({ location, trusted }) => { expect(isTrustedUrlOrPath(location)).toBe(trusted); diff --git a/components/dashboard/src/utils.ts b/components/dashboard/src/utils.ts index 36048fe7104276..88421602e02021 100644 --- a/components/dashboard/src/utils.ts +++ b/components/dashboard/src/utils.ts @@ -227,7 +227,9 @@ export function parseUrl(url: string): URL | null { export function isTrustedUrlOrPath(urlOrPath: string) { const url = parseUrl(urlOrPath); - const isTrusted = url ? window.location.hostname === url.hostname : urlOrPath.startsWith("/"); + const isTrusted = url + ? window.location.hostname === url.hostname && url.protocol === "https:" + : urlOrPath.startsWith("/"); if (!isTrusted) { console.warn("Untrusted URL", urlOrPath); }