wger: Privilege escalation via trainer-login session chaining allows gym trainer to impersonate gym manager
Date: 2026-05
Affected: pip/wger
Attack vector: deepfake
Category: vulnerability-disclosure
Severity: High
CVE: CVE-2026-43978
CWE: CWE-269
CVSS: 8.1 (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N)

### Summary A gym trainer can escalate their session to any higher-privileged account (gym manager, general manager) by chaining two calls to the trainer-login endpoint. Once a trainer performs a legitimate switch into a low-privileged user, the session flag `trainer.identity` is set and this flag alone bypasses the permission check on all subsequent trainer-login calls, allowing the trainer to hop into any account including gym managers. ### Details In `wger/core/views/user.py` lines 169–178, the permission check uses an AND condition: ```python # Line 169 — passes if EITHER condition is false if not request.user.has_perm('gym.gym_trainer') and not request.session.get('trainer.identity'): return HttpResponseForbidden() # Line 173 — only runs when current user IS a trainer, not when identity is inherited if request.user.has_perm('gym.gym_trainer') and ( user.has_perm('gym.manage_gym') or user.has_perm('gym.manage_gyms') ): return HttpResponseForbidden() ``` After hop 1 (trainer → regular user), `request.user` is the regular user who has no `gym_trainer` permission, but `session['trainer.identity']` is set. Line 169 evaluates: `not False AND not False` → the second operand short-circuits the check. Line 173 is never reached because the current user is no longer a trainer. The attacker can therefore call trainer-login again targeting a manager account and it succeeds. ### PoC Requirements: A running wger instance with at least one gym trainer account and one g


Mitigations:

Architectural layers (MAESTRO):