From 9ed02c7b8b018b6dcec90a6bb400f2cd51c7b88e Mon Sep 17 00:00:00 2001 From: Brendan Kellam Date: Wed, 29 Apr 2026 20:11:30 -0700 Subject: [PATCH 1/2] chore(web): harden post-auth redirects and legacy URL rewrite MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add explicit `redirect` callback to the NextAuth config that pins post-auth redirects to the same origin. This mirrors the documented Auth.js default but makes the protection visible in code rather than relying on upstream defaults. - Switch the legacy `/~/...` rewrite in `proxy.ts` from 308 to 301. The rewrite is a backwards-compat shim for v3.0.0–v4.16.8 page URLs, which are virtually all GETs; 301 has matching cache/permanence semantics but downgrades any stray POST to GET and drops the body. Co-Authored-By: Claude Opus 4.7 (1M context) --- packages/web/src/auth.ts | 20 ++++++++++++++++++++ packages/web/src/proxy.ts | 5 +++-- 2 files changed, 23 insertions(+), 2 deletions(-) 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(); From 89166db6351741623439f9727231ae958fb803d3 Mon Sep 17 00:00:00 2001 From: Brendan Kellam Date: Wed, 29 Apr 2026 20:12:10 -0700 Subject: [PATCH 2/2] docs: add CHANGELOG entry for #1161 Co-Authored-By: Claude Opus 4.7 (1M context) --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) 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)