Prevent non-admin users from impersonating admin users (#20412)

## Summary
- Adds a privilege check to workspace-level impersonation: non-admin
users can no longer impersonate users who have `canAccessFullAdminPanel`
or `canImpersonate` flags
- Adds the same check in JWT token validation as defense-in-depth
(invalidates existing impersonation sessions targeting admin users)
- Adds 3 unit tests covering: non-admin → admin blocked, non-admin →
canImpersonate blocked, admin → admin allowed

## Test plan
- [x] Unit tests pass (14/14 in `impersonation.service.spec.ts`)
- [x] Typecheck passes
- [ ] Verify workspace-level impersonation of regular users still works
normally
- [ ] Verify server-level impersonation by admins is unaffected

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Félix Malfait
2026-05-09 11:57:38 +02:00
committed by GitHub
parent 3420d63b7a
commit 459c64f642
3 changed files with 201 additions and 0 deletions
@@ -338,6 +338,21 @@ export class JwtAuthStrategy extends PassportStrategy(Strategy, 'jwt') {
);
}
const targetHasAdminPrivileges =
impersonatedUserWorkspace.user.canImpersonate === true ||
impersonatedUserWorkspace.user.canAccessFullAdminPanel === true;
const impersonatorHasAdminPrivileges =
impersonatorUserWorkspace.user.canImpersonate === true ||
impersonatorUserWorkspace.user.canAccessFullAdminPanel === true;
if (targetHasAdminPrivileges && !impersonatorHasAdminPrivileges) {
throw new AuthException(
'Cannot impersonate a user with admin privileges',
AuthExceptionCode.FORBIDDEN_EXCEPTION,
);
}
return {
impersonatorUserWorkspaceId: payload.impersonatorUserWorkspaceId,
impersonatedUserWorkspaceId: payload.impersonatedUserWorkspaceId,