diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/clickmaps/clickmap-origins.test.ts b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/clickmaps/clickmap-origins.test.ts index 59e075b2f..719ea7171 100644 --- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/clickmaps/clickmap-origins.test.ts +++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/clickmaps/clickmap-origins.test.ts @@ -31,4 +31,9 @@ describe("clickmap origin options", () => { expect(normalizeClickmapOrigin("https://app.dev.stack-auth.com/dashboard")).toMatchInlineSnapshot(`"https://app.dev.stack-auth.com"`); expect(normalizeClickmapOrigin("javascript:alert(1)")).toMatchInlineSnapshot(`null`); }); + + it("rejects wildcard origins to prevent percent-encoded URLs", () => { + expect(normalizeClickmapOrigin("https://**.example.com")).toMatchInlineSnapshot(`null`); + expect(normalizeClickmapOrigin("https://*.stack-auth.com")).toMatchInlineSnapshot(`null`); + }); }); diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/clickmaps/clickmap-origins.ts b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/clickmaps/clickmap-origins.ts index 69276991a..a3bb78c7b 100644 --- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/clickmaps/clickmap-origins.ts +++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/clickmaps/clickmap-origins.ts @@ -1,3 +1,5 @@ +import { stringCompare } from "@hexclave/shared/dist/utils/strings"; + export type ClickmapOrigin = { id: string, origin: string, @@ -9,6 +11,10 @@ export type ClickmapWildcardDomain = { }; export function normalizeClickmapOrigin(baseUrl: string): string | null { + if (baseUrl.includes("*")) { + return null; + } + let url: URL; try { url = new URL(baseUrl); @@ -27,16 +33,6 @@ function isWildcardDomain(baseUrl: string): boolean { return baseUrl.includes("*"); } -function compareStrings(a: string, b: string): number { - if (a < b) { - return -1; - } - if (a > b) { - return 1; - } - return 0; -} - export function getClickmapOriginOptions(trustedDomains: Record): { origins: ClickmapOrigin[], wildcardDomains: ClickmapWildcardDomain[], @@ -63,7 +59,7 @@ export function getClickmapOriginOptions(trustedDomains: Record compareStrings(a.origin, b.origin)), - wildcardDomains: wildcardDomains.sort((a, b) => compareStrings(a.baseUrl, b.baseUrl)), + origins: Array.from(byOrigin.values()).sort((a, b) => stringCompare(a.origin, b.origin)), + wildcardDomains: wildcardDomains.sort((a, b) => stringCompare(a.baseUrl, b.baseUrl)), }; }