From 8cf2e010a78d760e1bcc50448f29772ac95d54fb Mon Sep 17 00:00:00 2001 From: jsdavid278-cyber Date: Sat, 13 Jun 2026 16:26:41 -0600 Subject: [PATCH] Sanitize affiliate tracking code prefixes --- src/lib/affiliates/tracking.test.ts | 13 +++++++++++++ src/lib/affiliates/tracking.ts | 7 ++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/lib/affiliates/tracking.test.ts b/src/lib/affiliates/tracking.test.ts index ab474473..c0248b8a 100644 --- a/src/lib/affiliates/tracking.test.ts +++ b/src/lib/affiliates/tracking.test.ts @@ -98,6 +98,19 @@ describe("generateTrackingCode", () => { expect(code1).toMatch(/^bob-[a-f0-9]{6}$/); expect(code2).toMatch(/^bob-[a-f0-9]{6}$/); }); + + it("sanitizes username prefixes for URL-safe tracking codes", () => { + const code = generateTrackingCode("Alice Smith/@Example", "offer-1"); + + expect(code).toMatch(/^alice-smith-example-[a-f0-9]{6}$/); + expect(code).not.toMatch(/[ /@]/); + }); + + it("falls back when the username has no URL-safe characters", () => { + const code = generateTrackingCode("!!!", "offer-1"); + + expect(code).toMatch(/^affiliate-[a-f0-9]{6}$/); + }); }); describe("hashIP", () => { diff --git a/src/lib/affiliates/tracking.ts b/src/lib/affiliates/tracking.ts index fc066840..e4055bc1 100644 --- a/src/lib/affiliates/tracking.ts +++ b/src/lib/affiliates/tracking.ts @@ -19,12 +19,17 @@ async function getAttributionWindowStart(admin: SupabaseClient, offerId: string) */ export function generateTrackingCode(username: string, offerSlug: string): string { const base = `${username}-${offerSlug}`; + const prefix = username + .toLowerCase() + .replace(/[^a-z0-9]+/g, "-") + .replace(/^-+|-+$/g, "") + .slice(0, 48) || "affiliate"; const hash = crypto .createHash("sha256") .update(base + Date.now()) .digest("hex") .slice(0, 6); - return `${username}-${hash}`; + return `${prefix}-${hash}`; } /**