Skip to content
WebCureby Swasti
High

Admin pages hidden, not protected

The admin button is hidden in the UI, but the admin API answers anyone.

What it is

Admin features are hidden by not showing a button, while the page or API behind it has no server-side role check. Anyone who finds the URL can use it.

Why fast-built apps get it

It's natural to “protect” admin with if (user.isAdmin) in a component. AI tools copy that pattern, and admin URLs leak through JavaScript bundles and sitemaps.

Before and after the cure

app/admin/page.tsxVulnerable
"use client";
export default function Admin() {
  const { user } = useUser();
  if (!user?.isAdmin) return null;  // only hides the UI
  return <UsersTable />;            // which calls /api/admin/users freely
}
app/api/admin/users/route.tsCured
export async function GET(req: Request) {
  const user = await requireUser(req);
  if (user.role !== "admin") {
    return new Response("Forbidden", { status: 403 });
  }
  return Response.json(await db.user.findMany());
}

What it can cost you

  • Users granting themselves free plans or credits
  • Bulk exports of all customers
  • Changes to other users' accounts

Check your own app

  • Search your JS bundle for “/admin” and try those URLs logged in as a normal user
  • Check every admin API route checks the role on the server
  • Look for role or isAdmin values read from the client

The cure

  • Check roles on the server for every admin page and API
  • Read roles from your database or signed session, never from the client
  • Log every admin action with who did it

Does your app have this one?

We'll check this and every other loophole on your app, then give you the cure.

Talk to us on WhatsApp