Sensitive routes without authentication checks
Authentication and authorization are two different things. Auth checks that a user is logged in. Authorization checks that the logged-in user is allowed to do this specific action. This check covers the first one: any sensitive route that is reachable without being logged in at all.
#What goes wrong
When you ask an AI to build a new admin route or a user data endpoint, it often forgets to check the session. The route works in testing because you happen to be logged in. In production, anyone who finds the URL can hit it.
#Why it matters
Unprotected routes are how data dumps happen. An attacker scrapes your site, finds an /api/users endpoint that returns the full user table, and your entire customer list ends up on a forum. The route was never linked from the UI, but that is not protection.
#How Heimdall checks for this
Heimdall reads your middleware matchers and your sensitive API routes. It filters out routes that are public by design, like webhooks, signup, and login. For everything that is left, it verifies that either the middleware enforces auth or the route handler does the check itself before any data operation.
#How to fix it
Add an auth check at the top of every sensitive route handler, or use middleware to gate all routes that match a pattern like /api/admin or /api/account. Return 401 if no session, then return 403 if the user is logged in but not allowed. Run the check before any database call.
Frequently asked questions
Should I use middleware or check inside each handler?
Are server actions protected automatically?
How do I find unprotected routes in a large project?
Run this check on your own repo
Heimdall scans your GitHub repo for this and 16 other issues in under a minute.
