← Back to VibeScan
HighSecurity Finding

Admin Route Accessible Without Authentication

VibeScan found an admin or sensitive API endpoint that returns a 200 response to unauthenticated requests. This means anyone on the internet can access it — no account, no session, no credentials required.

What we found

# Unauthenticated GET request returned 200 OK:
GET /api/admin/users → 200 OK
# Response body:
{"users": [{"id": 1, "email": "user@example.com", "role": "admin"}, ...]}

Why this is high severity

AI coding tools (Lovable, Bolt, Cursor) often scaffold admin dashboards and API routes but don't automatically add authentication checks. The route handler gets created, it works in your browser because you're logged in — but the auth check is never actually enforced server-side.

👤User enumeration: an attacker gets a full list of your users, emails, and roles
🔑Privilege escalation: if the route modifies user roles or settings, anyone can call it
💾Data exfiltration: sensitive records (orders, payments, private notes) get exposed
🗑️Destructive operations: delete endpoints are often unprotected too

How to fix it

1

Add a session check at the top of every admin route

Check for a valid session and verify the user has admin privileges before doing anything else. Return 401 or 403 immediately if not.

// Next.js App Router example
import { getServerSession } from 'next-auth'
import { authOptions } from '@/lib/auth'

export async function GET() {
  const session = await getServerSession(authOptions)
  
  if (!session) {
    return Response.json({ error: 'Unauthorized' }, { status: 401 })
  }
  
  if (session.user.role !== 'admin') {
    return Response.json({ error: 'Forbidden' }, { status: 403 })
  }
  
  // ... admin logic
}
2

Use middleware to protect entire route groups

Rather than adding auth checks to every route individually, use Next.js middleware to protect all /admin/* and /api/admin/* routes at once.

// middleware.ts
import { withAuth } from 'next-auth/middleware'

export default withAuth({
  callbacks: {
    authorized: ({ token }) => token?.role === 'admin',
  },
})

export const config = {
  matcher: ['/admin/:path*', '/api/admin/:path*'],
}
3

Test with a logged-out browser

Open an incognito window and manually navigate to /api/admin/users. You should receive a 401, not a 200 with data. If you get data, the fix didn't work.

Fix prompt for Lovable / Bolt / Cursor

“VibeScan found that my admin API routes are accessible without authentication. Please add proper auth checks to all routes under /api/admin/* so that only users with the admin role can access them. Unauthenticated requests should return 401. Non-admin authenticated users should return 403. Use middleware to protect the entire /admin and /api/admin route group rather than adding checks to each route individually.”

Find all unprotected routes in your app

VibeScan probes common admin and API routes alongside 10 other checks — free, in under 60 seconds.

Scan my app free →