Hardcoded Admin Credentials
Admin Safety · ADM-11 · Priority: P0
Why It Matters
AI code generators frequently hardcode admin credentials during development — admin emails, passwords, or API keys directly in source code. Once pushed to a repository, these credentials remain in git history even after deletion. Anyone with repo access (or access to a leaked repo) can use them to gain full admin control.
Priority: P0 — Hardcoded admin credentials give attackers immediate admin access.
Affected Stack: Any framework, any database
The Problem
Common patterns AI tools generate:
// ❌ Hardcoded admin check
const ADMIN_EMAIL = "admin@company.com";
const ADMIN_PASSWORD = "admin123";
if (email === ADMIN_EMAIL && password === ADMIN_PASSWORD) {
// Grant admin access
}
// ❌ Hardcoded admin list in source
const ADMIN_EMAILS = ["founder@startup.com", "dev@startup.com"];
function isAdmin(email: string) {
return ADMIN_EMAILS.includes(email);
}
The Fix
1. Store admin identifiers in the database
// ✅ Role stored in database, not in code
const { data: profile } = await supabase
.from('profiles')
.select('role')
.eq('user_id', user.id)
.single();
if (profile?.role !== 'admin') {
return new Response('Forbidden', { status: 403 });
}
2. Use Supabase app_metadata for role assignment
// ✅ Role in Supabase auth metadata (not guessable, not in code)
const { data: { user } } = await supabase.auth.getUser();
const role = user?.app_metadata?.role;
if (role !== 'admin') {
return new Response('Forbidden', { status: 403 });
}
3. If credentials were ever committed
Even if you delete the hardcoded credentials from code, they remain in git history. Rotate all affected credentials immediately and consider using git filter-branch or BFG Repo-Cleaner to purge history.
References
Related Checks
- Exposed Debug & Admin Routes — ADM-08
- Server-Side Auth for Protected Routes — ADM-01, ADM-02
Is your app safe? Run Free Scan →