Check for missing authentication on API routes
Scans API routes for missing authentication and authorization vulnerabilities.
/plugin marketplace add Rahat-ch/vibe-check/plugin install rahat-ch-vibe-check@Rahat-ch/vibe-checkScan API routes for missing authentication and authorization.
Usage: /vibe-check:auth
Next.js App Router:
app/api/**/route.ts
app/api/**/route.js
Next.js Pages Router:
pages/api/**/*.ts
pages/api/**/*.js
Other Frameworks:
src/routes/** (SvelteKit)server/api/** (Nuxt)api/** (generic)Next-Auth (App Router):
import { getServerSession } from "next-auth";
import { auth } from "@/auth"; // v5
const session = await getServerSession(authOptions);
const session = await auth();
Next-Auth (Pages Router):
import { getSession } from "next-auth/react";
const session = await getSession({ req });
Supabase Auth:
import { createRouteHandlerClient } from "@supabase/auth-helpers-nextjs";
const { data: { session } } = await supabase.auth.getSession();
Clerk:
import { auth } from "@clerk/nextjs";
const { userId } = auth();
Custom Auth:
if (!req.headers.authorization)
const token = req.cookies.get("session")
For each route handler (GET, POST, PUT, DELETE, PATCH):
Severity:
Look for auth middleware:
Next.js middleware.ts:
// middleware.ts
import { withAuth } from "next-auth/middleware";
export default withAuth(...);
export const config = { matcher: ["/api/:path*"] };
If middleware protects routes, reduce severity of findings.
Beyond authentication, check for authorization:
User accessing own data:
// Good
const user = await getUser(session.user.id);
if (user.id !== session.user.id) return forbidden();
// Bad - no ownership check
const user = await getUser(params.userId);
return Response.json(user);
For Next.js 14+, check server actions:
// app/actions.ts
"use server"
export async function updateProfile(data: FormData) {
// Does this check auth?
const session = await auth();
if (!session) throw new Error("Unauthorized");
}
[HIGH] Unprotected API Route
File: app/api/users/[id]/route.ts:8
Handler: DELETE
Issue: No authentication check before deleting user
Risk: Any client can delete any user account
Fix:
import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth";
export async function DELETE(
request: Request,
{ params }: { params: { id: string } }
) {
const session = await getServerSession(authOptions);
if (!session) {
return Response.json(
{ error: "Unauthorized" },
{ status: 401 }
);
}
// Also check authorization
if (session.user.id !== params.id) {
return Response.json(
{ error: "Forbidden" },
{ status: 403 }
);
}
// Now safe to delete
await deleteUser(params.id);
return Response.json({ success: true });
}