From a70ad7c6b7f2c3544c1281e8ae08c0837afa8f3a Mon Sep 17 00:00:00 2001 From: ZacharyZcR Date: Sun, 9 Nov 2025 09:16:11 +0800 Subject: [PATCH] security: Fix user enumeration vulnerability in login - Unify error messages for invalid username and incorrect password - Both return 401 status with 'Invalid username or password' - Prevent attackers from enumerating valid usernames - Maintain detailed logging for debugging purposes - Changed from 404 'User not found' to generic auth failure message --- src/backend/database/routes/users.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/backend/database/routes/users.ts b/src/backend/database/routes/users.ts index 7f21cbae..92ea8746 100644 --- a/src/backend/database/routes/users.ts +++ b/src/backend/database/routes/users.ts @@ -896,11 +896,11 @@ router.post("/login", async (req, res) => { .where(eq(users.username, username)); if (!user || user.length === 0) { - authLogger.warn(`User not found: ${username}`, { + authLogger.warn(`Login failed: user not found`, { operation: "user_login", username, }); - return res.status(404).json({ error: "User not found" }); + return res.status(401).json({ error: "Invalid username or password" }); } const userRecord = user[0]; @@ -918,12 +918,12 @@ router.post("/login", async (req, res) => { const isMatch = await bcrypt.compare(password, userRecord.password_hash); if (!isMatch) { - authLogger.warn(`Incorrect password for user: ${username}`, { + authLogger.warn(`Login failed: incorrect password`, { operation: "user_login", username, userId: userRecord.id, }); - return res.status(401).json({ error: "Incorrect password" }); + return res.status(401).json({ error: "Invalid username or password" }); } try {