Skip to content

Use current origin for referral links - #128

Closed
absalonCRC wants to merge 1 commit into
profullstack:masterfrom
absalonCRC:fix-referral-link-origin
Closed

Use current origin for referral links#128
absalonCRC wants to merge 1 commit into
profullstack:masterfrom
absalonCRC:fix-referral-link-origin

Conversation

@absalonCRC

@absalonCRC absalonCRC commented May 21, 2026

Copy link
Copy Markdown
Contributor

Summary

  • build referral invite links from NEXT_PUBLIC_APP_URL or the current request origin instead of hardcoding production
  • URL-encode referral codes before placing them in the invite URL
  • add regression coverage for request-origin fallback and configured app URL behavior

Fixes #127

Validation

  • pnpm test:run src/app/api/referrals/code/route.test.ts
  • pnpm type-check
  • pnpm exec eslint src/app/api/referrals/code/route.ts src/app/api/referrals/code/route.test.ts
  • git diff --check

Bounty / payment

Submitted for the active uGig affiliate-program testing task. SOL receive address: 27sdMYXofqoM9qR13bZhccRNYeEgYn5EoHXTSJn4QWKP.

Payment fallback: PayPal cultofrozen@gmail.com

@greptile-apps

greptile-apps Bot commented May 23, 2026

Copy link
Copy Markdown

Greptile Summary

This PR fixes referral invite links so they are built from NEXT_PUBLIC_APP_URL or the current request origin instead of a hardcoded production domain, and adds encodeURIComponent around the referral code.

  • route.ts: Base URL is now resolved via NEXT_PUBLIC_APP_URL || request.nextUrl.origin || "https://ugig.net" with trailing-slash normalisation; the referral code is properly URL-encoded before being appended.
  • route.test.ts: Adds beforeEach/afterEach env-var lifecycle management and a new test that exercises the NEXT_PUBLIC_APP_URL preference and URL-encoding behaviour.

Confidence Score: 3/5

Safe to merge only if NEXT_PUBLIC_APP_URL is guaranteed to be set in every deployment; without it, the request-origin fallback exposes a host-header injection path.

The core fix (URL-encoding the referral code, removing the hardcoded domain) is correct and well-tested. The risk is the intermediate fallback: using request.nextUrl.origin means any deployment that omits NEXT_PUBLIC_APP_URL can be induced — by a manipulated Host header — to return a referral link pointing at an attacker-controlled domain. That's a present defect on the changed code path, not a theoretical one.

src/app/api/referrals/code/route.ts — specifically the base URL resolution at line 25.

Security Review

  • Host-header injection (src/app/api/referrals/code/route.ts, line 25): when NEXT_PUBLIC_APP_URL is absent, the referral link base URL is taken from request.nextUrl.origin, which is derived from the attacker-controlled Host header. An authenticated user can force the API to generate a referral link pointing to an arbitrary domain.

Important Files Changed

Filename Overview
src/app/api/referrals/code/route.ts Replaces hardcoded production URL with a dynamic base URL derived from NEXT_PUBLIC_APP_URL or request origin; adds encodeURIComponent on the referral code. The request-origin fallback is susceptible to Host-header injection.
src/app/api/referrals/code/route.test.ts Adds env-var lifecycle management (beforeEach/afterEach) and a new test covering NEXT_PUBLIC_APP_URL preference and URL-encoding of referral codes. Cleanup logic is correct.

Sequence Diagram

sequenceDiagram
    participant Client
    participant GET /api/referrals/code
    participant Supabase

    Client->>GET /api/referrals/code: GET (with Host header)
    GET /api/referrals/code->>Supabase: select referral_code, username where id=user.id
    Supabase-->>GET /api/referrals/code: { referral_code, username }
    note over GET /api/referrals/code: baseUrl = NEXT_PUBLIC_APP_URL<br/>|| request.nextUrl.origin ⚠️<br/>|| "https://ugig.net"
    GET /api/referrals/code-->>Client: { code, link: baseUrl + "/?ref=" + encodeURIComponent(code) }
Loading

Reviews (1): Last reviewed commit: "Use current origin for referral links" | Re-trigger Greptile


const code = profile.referral_code || profile.username;
const baseUrl = (
process.env.NEXT_PUBLIC_APP_URL || request.nextUrl.origin || "https://ugig.net"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 security Host-header injection in referral link base URL

When NEXT_PUBLIC_APP_URL is not set (e.g., a self-hosted or staging deployment without the env var configured), request.nextUrl.origin is derived directly from the incoming Host HTTP header. An authenticated user can craft a request with Host: evil.com, causing the API to return link: "https://evil.com/?ref=...". If that link is displayed in the UI or copied by the user and shared, it becomes a phishing vector under the guise of a legitimate referral invite.

The safest fix is to validate request.nextUrl.origin against a known allowlist, or to rely solely on NEXT_PUBLIC_APP_URL and the hardcoded production fallback — dropping the origin fallback entirely.

@ralyodio ralyodio closed this May 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: referral code API returns production invite links on non-production origins

2 participants