Auth Logic in Frontend Only
Showing or hiding UI elements based on user role in React, without any server-side enforcement — easily bypassed by anyone who opens DevTools.
How It Works
React renders on the client. Any `if (user.role === 'admin')` check in your JSX is just JavaScript that anyone can read and manipulate. Hiding a button doesn't protect the endpoint behind it. Attackers call the API directly, skipping your UI entirely.
// BAD: admin panel hidden in UI but API unprotected
function Dashboard({ user }) {
return (
<div>
{user.role === 'admin' && <AdminPanel />}
</div>
);
}
// The /api/admin route has no auth check// GOOD: enforce on the server, mirror in UI
// API route:
export async function GET() {
const user = await getAuthenticatedUser();
if (user.role !== 'admin') {
return Response.json({ error: 'Forbidden' }, { status: 403 });
}
return Response.json(await getAdminData());
}Real-World Example
A vibecoder built a SaaS where the 'delete all users' button was hidden for non-admins. A curious user opened the Network tab, copied the fetch() call to the /api/admin/users endpoint, and ran it in the console. All users deleted.
How to Prevent It
- Every sensitive API route must check user role/permissions server-side, always
- Treat all client-side auth checks as UX only — never as security
- Use middleware or a reusable auth helper to enforce roles on every protected route
- Test your API routes directly with curl or Postman without a valid session
Affected Technologies
Data Hogo detects this vulnerability automatically.
Scan Your Repo FreeRelated Vulnerabilities
Hardcoded API Keys
criticalAPI keys, tokens, or secrets written directly in source code, making them visible to anyone with repo access — including public GitHub repositories.
No Input Validation
mediumUser-supplied data sent directly to databases or external APIs without any type, format, or content validation.
Passwords Stored in Plaintext
criticalUser passwords stored as raw strings in the database instead of being hashed with a proper algorithm like bcrypt or Argon2.
JWT Without Expiration
highJWTs signed without an `exp` claim that never expire, meaning a stolen token grants permanent access with no way to revoke it.