Summary
src/lib/supabase/middleware.ts includes /api in the PUBLIC_ROUTES array. The isPublicRoute() function matches any path starting with /api/, effectively making ALL API endpoints publicly accessible at the middleware level.
Location
// src/lib/supabase/middleware.ts
const PUBLIC_ROUTES = [
"/",
"/login",
"/register",
// ...
"/api", // This makes ALL /api/* routes "public"
// ...
];
function isPublicRoute(pathname: string): boolean {
return PUBLIC_ROUTES.some(
(route) => pathname === route || pathname.startsWith(route + "/")
);
}
Impact
The middleware skips Supabase session refresh for ALL API routes. While each API route handler does its own supabase.auth.getUser() check, the middleware would normally:
- Refresh expired session tokens automatically
- Redirect unauthenticated users
By marking /api as public, the middleware provides no defense-in-depth for API routes. If any API handler forgets the auth check, it becomes an unauthenticated endpoint.
This is particularly concerning because:
/api/webhooks/* are intentionally public (receives from Twilio/Telnyx)
- But
/api/messages/*, /api/contacts/*, /api/campaigns/* should NOT be public at middleware level
- The intent was likely to only expose
/api/health and /api/webhooks/* as public
Suggested Fix
Replace the broad /api entry with specific public API paths:
const PUBLIC_ROUTES = [
// ...
"/api/health",
"/api/webhooks",
"/api/waitlist",
// NOT "/api" — too broad
];
Severity
Medium — Defense-in-depth gap. Individual route handlers still check auth, but one missing check = full vulnerability.
Summary
src/lib/supabase/middleware.tsincludes/apiin thePUBLIC_ROUTESarray. TheisPublicRoute()function matches any path starting with/api/, effectively making ALL API endpoints publicly accessible at the middleware level.Location
Impact
The middleware skips Supabase session refresh for ALL API routes. While each API route handler does its own
supabase.auth.getUser()check, the middleware would normally:By marking
/apias public, the middleware provides no defense-in-depth for API routes. If any API handler forgets the auth check, it becomes an unauthenticated endpoint.This is particularly concerning because:
/api/webhooks/*are intentionally public (receives from Twilio/Telnyx)/api/messages/*,/api/contacts/*,/api/campaigns/*should NOT be public at middleware level/api/healthand/api/webhooks/*as publicSuggested Fix
Replace the broad
/apientry with specific public API paths:Severity
Medium — Defense-in-depth gap. Individual route handlers still check auth, but one missing check = full vulnerability.