Skip to content

Commit

Permalink
security: encode UTM cookies on write, decode on read
Browse files Browse the repository at this point in the history
  • Loading branch information
Eliezer Steinbock committed Jan 6, 2026
1 parent a9908ef commit eb27d59
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 13 deletions.
21 changes: 15 additions & 6 deletions apps/web/app/(landing)/welcome/utms.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,24 @@ export function registerUtmTracking({
// See: https://nextjs.org/docs/app/api-reference/functions/after
export function extractUtmValues(cookies: ReadonlyRequestCookies): UtmValues {
return {
utmCampaign: cookies.get("utm_campaign")?.value,
utmMedium: cookies.get("utm_medium")?.value,
utmSource: cookies.get("utm_source")?.value,
utmTerm: cookies.get("utm_term")?.value,
affiliate: cookies.get("affiliate")?.value,
referralCode: cookies.get("referral_code")?.value,
utmCampaign: decodeCookieValue(cookies.get("utm_campaign")?.value),
utmMedium: decodeCookieValue(cookies.get("utm_medium")?.value),
utmSource: decodeCookieValue(cookies.get("utm_source")?.value),
utmTerm: decodeCookieValue(cookies.get("utm_term")?.value),
affiliate: decodeCookieValue(cookies.get("affiliate")?.value),
referralCode: decodeCookieValue(cookies.get("referral_code")?.value),
};
}

function decodeCookieValue(value: string | undefined): string | undefined {
if (!value) return undefined;
try {
return decodeURIComponent(value);
} catch {
return value;
}
}

export async function fetchUserAndStoreUtms(
userId: string,
utmValues: UtmValues,
Expand Down
12 changes: 6 additions & 6 deletions apps/web/app/utm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,17 @@ function setUtmCookies() {
const expires = new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toUTCString();

if (utmSource)
document.cookie = `utm_source=${utmSource}; expires=${expires}; path=/; SameSite=Lax; Secure`;
document.cookie = `utm_source=${encodeURIComponent(utmSource)}; expires=${expires}; path=/; SameSite=Lax; Secure`;
if (utmMedium)
document.cookie = `utm_medium=${utmMedium}; expires=${expires}; path=/; SameSite=Lax; Secure`;
document.cookie = `utm_medium=${encodeURIComponent(utmMedium)}; expires=${expires}; path=/; SameSite=Lax; Secure`;
if (utmCampaign)
document.cookie = `utm_campaign=${utmCampaign}; expires=${expires}; path=/; SameSite=Lax; Secure`;
document.cookie = `utm_campaign=${encodeURIComponent(utmCampaign)}; expires=${expires}; path=/; SameSite=Lax; Secure`;
if (utmTerm)
document.cookie = `utm_term=${utmTerm}; expires=${expires}; path=/; SameSite=Lax; Secure`;
document.cookie = `utm_term=${encodeURIComponent(utmTerm)}; expires=${expires}; path=/; SameSite=Lax; Secure`;
if (affiliate)
document.cookie = `affiliate=${affiliate}; expires=${expires}; path=/; SameSite=Lax; Secure`;
document.cookie = `affiliate=${encodeURIComponent(affiliate)}; expires=${expires}; path=/; SameSite=Lax; Secure`;
if (referralCode)
document.cookie = `referral_code=${referralCode}; expires=${expires}; path=/; SameSite=Lax; Secure`;
document.cookie = `referral_code=${encodeURIComponent(referralCode)}; expires=${expires}; path=/; SameSite=Lax; Secure`;
}

export function UTM() {
Expand Down
7 changes: 6 additions & 1 deletion apps/web/utils/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,12 @@ export async function handleReferralOnSignUp({
return;
}

const referralCode = referralCookie.value;
let referralCode = referralCookie.value;
try {
referralCode = decodeURIComponent(referralCode);
} catch {
// Use original value if decoding fails
}
logger.info("Processing referral for new user", {
email,
referralCode,
Expand Down

0 comments on commit eb27d59

Please sign in to comment.