mirror of
https://github.com/multica-ai/multica.git
synced 2026-07-13 13:18:56 +02:00
* refactor(auth): add sanitizeNextUrl helper in @multica/core/auth Extracts a reusable helper that returns a post-login redirect URL only when it's a safe single-slash relative path, and null otherwise. Rejects absolute URLs, protocol-relative URLs, backslashes, and control characters so call sites can safely pass the result to router.push(). Keeping the rule in a single helper (with direct unit tests) avoids each consumer re-implementing the validation and drifting. * fix(auth): validate next= redirect target to prevent open redirect Closes #1116 Next.js router.push accepts absolute URLs, so a crafted `/login?next=https://evil.example` would send the user off-origin after a successful login. The Google OAuth callback has the same vector via the `state=next:<url>` payload. Sanitize both entry points through `sanitizeNextUrl` from `@multica/core/auth` so only safe single-slash relative paths survive; null results fall through to the existing workspace-list-based default without any hard-coded path. --------- Co-authored-by: JunghwanNA <70629228+shaun0927@users.noreply.github.com>
21 lines
830 B
TypeScript
21 lines
830 B
TypeScript
/**
|
||
* Validate a post-login redirect URL and return it only if safe to follow.
|
||
*
|
||
* Only single-slash relative paths (e.g. `/invite/abc`) are accepted. Returns
|
||
* `null` for unsafe or empty input — call sites decide the fallback so this
|
||
* helper never overloads a specific path with "user did not pass next".
|
||
*
|
||
* Rejects:
|
||
* - `null` / empty string
|
||
* - absolute URLs (`https://evil.com`, `javascript:alert(1)`, …)
|
||
* - protocol-relative URLs (`//evil.com`)
|
||
* - paths containing backslashes (Windows-style or `/\\host`)
|
||
* - paths containing ASCII control characters (`\x00`–`\x1f`)
|
||
*/
|
||
export function sanitizeNextUrl(raw: string | null): string | null {
|
||
if (!raw) return null;
|
||
if (!raw.startsWith("/") || raw.startsWith("//")) return null;
|
||
if (/[\x00-\x1f\\]/.test(raw)) return null;
|
||
return raw;
|
||
}
|