GHSA-mw8f-w6p8-xrf4: wger: cross-tenant account deletion / deactivation / activation by gym.manage_gym + gym=None
GHSA-mhc8-p3jx-84mm (CVE-2026-43948) reported that wger’s reset_user_password and gym_permissions_user_edit views in wger/gym/views/user.py performed a gym-scope authorization check using Django ORM object comparison (if request.user.userprofile.gym != user.userprofile.gym) which silently passes when both sides are None (None != None evaluates to False). The maintainer’s suggested patch (“Apply the same same_gym() helper pattern to all five views sharing this check”) replaces every userprofile.gym != site with the new is_same_gym() helper that explicitly excludes None (gym_a is not None and gym_a == gym_b).
The fix landed in wger/gym/views/{admin_notes,document,contract,gym}.py (5 views, all using is_same_gym). However, three additional views in wger/core/views/user.py were not migrated and retain the original userprofile.gym_id != ... raw integer comparison. Because raw integer != comparison still evaluates None != None as False, the gym-scope guard is bypassed identically to the patched views. The result is a complete incomplete-fix variant family that reproduces against the latest wger/server:latest Docker image (master, 2026-05-08 build).
A privileged-but-bounded gym staff user (admin-granted gym.manage_gym permission, intended scope: managing members of one specific gym) whose userprofile.gym = None (the default state before the admin links them to a gym) can:
- Permanently delete any other user with
gym = None(V3,deleteview, line 131 — CRITICAL data loss, irreversible) - Deactivate any other user with
gym = None, locking them out of the platform (V1,UserDeactivateView, line 405 — high availability impact) - Re-activate any previously deactivated user with
gym = None(V2,UserActivateView, line 442 — counters defensive deactivation)
Victim user pks are sequential integers and trivially enumerable via /en/user/<pk>/overview and other endpoints. The same_gym_id == ... flag in UserDetailView.get_context_data (line 587) is also affected, but the underlying dispatch() and the actual trainer_login view still use the patched is_same_gym() helper, so impersonation chain via that path is blocked at runtime — only the UI button visibility leaks. The three write-side variants above are the security boundary breaches.
References
Code Behaviors & Features
Detect and mitigate GHSA-mw8f-w6p8-xrf4 with GitLab Dependency Scanning
Secure your software supply chain by verifying that all open source dependencies used in your projects contain no disclosed vulnerabilities. Learn more about Dependency Scanning →