Skip to content

fix(auth): sanitize next redirects - #186

Merged
yakew7 merged 1 commit into
StudentSuite:mainfrom
AyobamiH:fix/sanitize-next-redirect
Aug 22, 2026
Merged

fix(auth): sanitize next redirects#186
yakew7 merged 1 commit into
StudentSuite:mainfrom
AyobamiH:fix/sanitize-next-redirect

Conversation

@AyobamiH

Copy link
Copy Markdown
Contributor

Closes #161.

What changed

  • Adds a shared safeNext helper for authentication redirects.
  • Accepts only root-relative same-origin paths.
  • Rejects absolute URLs, protocol-relative URLs, backslashes and ASCII control characters.
  • Uses the same sanitizer in both the email sign-in flow and OAuth callback.
  • Preserves query strings and fragments on valid internal paths.
  • Adds focused unit coverage for safe and unsafe redirect inputs.

Both redirect consumers now apply the same policy rather than relying on different client and server behaviour.

Verification

Final commit:

4ae07fb3d08a5ea42fc2164c00c74f58a2ed7467

On the final source:

  • npm run build passed
  • npm run lint passed
  • npx tsc --noEmit passed
  • place-data validation passed

Unit validation used the same source plus a temporary CI-only test job:

  • 12 test files passed
  • 108 tests passed
  • 16 safeNext cases passed

Validation PR:
AyobamiH#4

Signed-off-by: Ayobami Haastrup <47716486+AyobamiH@users.noreply.github.com>
@vercel

vercel Bot commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

@AyobamiH is attempting to deploy a commit to the studentsuite Team on Vercel.

A member of the Team first needs to authorize it.

@yakew7
yakew7 merged commit 943e11b into StudentSuite:main Aug 22, 2026
3 of 4 checks passed

@shauryagangrade shauryagangrade left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Review: sanitize next redirects (#161)

LGTM. Verified this covers both existing next consumers (grep get("next") over src returns exactly login-form.tsx and auth/callback/route.ts) — no stragglers.

The sanitizer handles the full known-bypass catalog:

  • absolute URLs and protocol-relative // / ///
  • backslashes (/\evil.example) — browsers normalize \/ in special schemes ✓
  • control chars incl. \t, \n, \0 — important because the WHATWG URL parser strips tabs/newlines, so /\n//evil.example would otherwise smuggle through a naive startsWith check ✓
  • relative junk (map, ?next=/map, #map) falls back to /
  • query strings and fragments survive on legitimate internal paths ✓

Tests pin all the adversarial cases, including the ones people usually forget (\u0000, tab/newline prefixes). CI green.

One optional future nicety, not blocking: if you ever want allowlist-level strictness, validating against the app's route table would catch typos like /maap — but same-origin-only is the correct security boundary here, and stricter than that is product territory.

Nice, tight security fix.

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/security: validate the ?next= redirect parameter — client-side router.push allows off-site navigation

3 participants