From 057640dd2308ff31acb26655eefcc068cab6828b Mon Sep 17 00:00:00 2001 From: ZacharyZcR Date: Sun, 21 Sep 2025 04:04:38 +0800 Subject: [PATCH] SECURITY FIX: Eliminate privilege escalation via database error exploitation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Critical Vulnerability Fixed: - Database errors during user count check resulted in automatic admin privileges - Any user could potentially gain admin access by triggering DB failures - Affected both regular user registration and OIDC user creation Root Cause Analysis: ```typescript } catch (e) { isFirstUser = true; // 💀 DANGEROUS: DB error = admin privileges ``` Linus-Style Solution - Fail Secure: ✅ Database error = reject request (don't guess permissions) ✅ Legitimate first user still gets admin (when DB works correctly) ✅ Attackers cannot exploit DB failures for privilege escalation ✅ Clear error logging for debugging Security Impact: - BEFORE: Database DoS → privilege escalation attack vector - AFTER: Database error → secure rejection, no privilege guessing Files Modified: • users.ts:221 - Fixed user registration privilege escalation • users.ts:670 - Fixed OIDC user creation privilege escalation "When in doubt, fail secure. Don't guess privileges." - Security Engineering 101 --- src/backend/database/routes/users.ts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/backend/database/routes/users.ts b/src/backend/database/routes/users.ts index 60964a8c..170e1645 100644 --- a/src/backend/database/routes/users.ts +++ b/src/backend/database/routes/users.ts @@ -218,12 +218,15 @@ router.post("/create", async (req, res) => { .get(); isFirstUser = ((countResult as any)?.count || 0) === 0; } catch (e) { - isFirstUser = true; - authLogger.warn("Failed to check user count, assuming first user", { + // SECURITY: Database error - fail secure, don't guess permissions + authLogger.error("Database error during user count check - rejecting request", { operation: "user_create", username, error: e, }); + return res.status(500).json({ + error: "Database unavailable - cannot create user safely" + }); } const saltRounds = parseInt(process.env.SALT || "10", 10); @@ -664,7 +667,13 @@ router.get("/oidc/callback", async (req, res) => { .get(); isFirstUser = ((countResult as any)?.count || 0) === 0; } catch (e) { - isFirstUser = true; + // SECURITY: Database error during OIDC user creation - fail secure + authLogger.error("Database error during OIDC user count check", { + operation: "oidc_user_create", + oidc_identifier: identifier, + error: e, + }); + throw new Error("Database unavailable - cannot create OIDC user safely"); } const id = nanoid();