From e72f3133c05ca477672e49f328681f95608421d8 Mon Sep 17 00:00:00 2001 From: delta-lynx-89e8 Date: Sun, 22 Feb 2026 12:40:09 -0800 Subject: [PATCH] Fix login endpoint leaking sensitive user fields Use select clause instead of spreading full user object to prevent resetToken, resetTokenExpiry, and other internal fields from being returned in the login response. Co-Authored-By: Claude Opus 4.6 --- server/src/routes/auth.ts | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/server/src/routes/auth.ts b/server/src/routes/auth.ts index 0ec3c2d..c7e5a28 100644 --- a/server/src/routes/auth.ts +++ b/server/src/routes/auth.ts @@ -53,19 +53,19 @@ router.post('/login', validate(loginSchema), async (req, res, next) => { try { const { email, password } = req.body; - const user = await prisma.user.findUnique({ where: { email } }); - if (!user) throw new AppError(401, 'Invalid email or password'); - if (!user.isActive) throw new AppError(403, 'Account is disabled'); + const fullUser = await prisma.user.findUnique({ where: { email } }); + if (!fullUser) throw new AppError(401, 'Invalid email or password'); + if (!fullUser.isActive) throw new AppError(403, 'Account is disabled'); - const valid = await comparePassword(password, user.passwordHash); + const valid = await comparePassword(password, fullUser.passwordHash); if (!valid) throw new AppError(401, 'Invalid email or password'); - const accessToken = generateAccessToken(user.id); - const refreshToken = generateRefreshToken(user.id); + const accessToken = generateAccessToken(fullUser.id); + const refreshToken = generateRefreshToken(fullUser.id); await prisma.session.create({ data: { - userId: user.id, + userId: fullUser.id, refreshToken, userAgent: req.headers['user-agent'] || null, ipAddress: req.ip || null, @@ -80,8 +80,11 @@ router.post('/login', validate(loginSchema), async (req, res, next) => { maxAge: 7 * 24 * 60 * 60 * 1000, }); - const { passwordHash: _, ...userData } = user; - res.json({ user: userData, accessToken }); + const user = await prisma.user.findUnique({ + where: { id: fullUser.id }, + select: { id: true, email: true, fullName: true, nickname: true, avatar: true, phone: true, location: true, bio: true, rating: true, showEmail: true, showPhone: true, showLocation: true, createdAt: true }, + }); + res.json({ user, accessToken }); } catch (error) { next(error); }