fix(security): block force-logout from targeting the admin's own session

The UI already disabled the per-row force-logout button for the active
admin (user-management-section.tsx:295), but the route handler had no
matching server-side check. A direct curl/DevTools call (or a
compromised admin session) could revoke the caller's own sessions and
bounce them to /auth/login mid-action.

Mirrors the UI gate with a 422 + an `admin.user.force-logout.denied`
audit entry tagged `reason: self_target`. Admin-on-admin force-logout
remains permitted (today's intentional behaviour).

Closes H1 from .planning/phase-6-code-review-findings.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Marc-André BombeckandClaude Opus 4.7 committed 2026-05-09 17:41:46 +02:00
1 parent 88c8db1abc
commit b3f282adab
1 file changed
+13
@@ -31,6 +31,19 @@ export const POST = apiHandler(
},
});
// Mirror the UI gate at user-management-section.tsx:295 — admins
// mid-action shouldn't bounce themselves to /auth/login. A
// determined admin can revoke another admin (intentional today),
// but the self-target case is always a footgun.
if (admin.id === id) {
await auditLog("admin.user.force-logout.denied", {
userId: admin.id,
ipAddress: getClientIp(request),
details: { targetUserId: id, reason: "self_target" },
});
return apiError("Cannot force-logout your own session", 422);
}
const target = await prisma.user.findUnique({
where: { id },
select: { id: true, username: true },