Why can my regular users see my admin page?
Because the admin page is protected by 'is this user logged in' but not 'is this user an admin'. Every vibe-coded app gets this wrong. The fix is adding a role check in the page's server-side auth guard. Hiding the admin link in the nav doesn't fix it — attackers type the URL directly.
This is one of the most common AI-coding-tool bugs — the model knows how to check 'is someone logged in' but often forgets to check 'is this the RIGHT someone'.
**Where the bug lives.** In Next.js, it's usually in your middleware or in the page's auth guard. Look for: ```ts if (!session) redirect('/login'); // ← bug: this only checks logged-in, not admin return <AdminPage />; ```
**The fix.** Add a role check server-side: ```ts if (!session) redirect('/login'); if (session.user.role !== 'admin') redirect('/'); return <AdminPage />; ```
**Common wrong fixes:** - Hiding the admin link in the nav bar. Useless — attackers type `/admin` directly. - Checking role in a client-side effect. Useless — the page renders before the effect runs, leaking data. - Checking role with a URL query parameter like `?admin=true`. Useless — anyone can set that. - Checking role in the component's render function. Useless unless the component is server-rendered AND the check happens before data fetching.
**Where the role data should live.** In your database (Supabase user_metadata or a separate `admins` table), NOT in cookies or JWTs alone. Client-side role storage can be forged.
Securie's scan (launching this year) will test every page in your app by logging in as a non-admin user and trying to access admin routes. Join the list for a week-1 run that flags every leak with the fix.