diff --git a/CHANGELOG.md b/CHANGELOG.md index 209582e2c..821e5462b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Added `/api/avatar` to resolve user profile pictures. [#1159](https://github.com/sourcebot-dev/sourcebot/pull/1159) +- Hardened post-auth redirects with an explicit same-origin `redirect` callback in the NextAuth config, and switched the legacy `/~/...` URL rewrite from a 308 to a 301. [#1161](https://github.com/sourcebot-dev/sourcebot/pull/1161) ### Fixed - Bumped `postcss` to `8.5.10`. [#1155](https://github.com/sourcebot-dev/sourcebot/pull/1155) diff --git a/packages/web/src/auth.ts b/packages/web/src/auth.ts index 001d11ef0..9ee2c1b05 100644 --- a/packages/web/src/auth.ts +++ b/packages/web/src/auth.ts @@ -220,6 +220,26 @@ export const { handlers, signIn, signOut, auth } = NextAuth({ } }, callbacks: { + // Restrict post-auth redirects (sign-in / sign-out, `callbackUrl`, + // `redirectTo`) to the same origin as the application. This mirrors + // Auth.js's documented default; we set it explicitly so the protection + // is visible in code and not dependent on upstream defaults. + // @see https://authjs.dev/reference/core#redirect + async redirect({ url, baseUrl }) { + if (url.startsWith("/")) { + return `${baseUrl}${url}`; + } + + try { + if (new URL(url).origin === baseUrl) { + return url; + } + } catch { + // Malformed URL — fall through to baseUrl. + } + + return baseUrl; + }, async jwt({ token, user: _user }) { const user = _user as User | undefined; // @note: `user` will be available on signUp or signIn triggers. diff --git a/packages/web/src/proxy.ts b/packages/web/src/proxy.ts index ed5cb73a1..0b07a5198 100644 --- a/packages/web/src/proxy.ts +++ b/packages/web/src/proxy.ts @@ -1,3 +1,4 @@ +import { StatusCodes } from 'http-status-codes'; import { NextResponse } from 'next/server' import type { NextRequest } from 'next/server' @@ -27,12 +28,12 @@ export async function proxy(request: NextRequest) { if (url.pathname.startsWith('/~/')) { url.pathname = url.pathname.replace(/^\/~/, ''); - return NextResponse.redirect(url, 308); + return NextResponse.redirect(url, StatusCodes.MOVED_PERMANENTLY); } if (url.pathname === '/~') { url.pathname = '/'; - return NextResponse.redirect(url, 308); + return NextResponse.redirect(url, StatusCodes.MOVED_PERMANENTLY); } return NextResponse.next();