Forums Bug Reports Thread

GateMiddleware reads $_SESSION['user_role'] which is never written — admin/role bypass in resolver never fires

Patrick Bass · Jun 6 · 11 · 1 Locked
[Minor] [Normal Priority] [Bug Fixed] [Always Reproduces]
🚀 OP Jun 6, 2026 8:05pm

Area: Cross-cutting infra (audit p14) · Surface: GateMiddleware -> GateAccessResolver role handling · Dimension: security · Severity: minor

OWASP A01. The mobieusGate access resolver has an intentional admin/staff bypass (role >= 4 → never gated), but the value driving it is read from a session key that is never populated. The bypass therefore never triggers via the middleware: a logged-in Administrator or Super Admin hitting a read_gated surface is treated as role 0 and shown the paywall instead of being let through. This is a correctness/access-policy bug — the gate behaves more restrictively than intended for staff, and the resolver's role logic is effectively dead through this call path.

Evidence

platform/src/Middleware/GateMiddleware.php:44 — `$userRole = (int) ($_SESSION['user_role'] ?? 0);` then GateMiddleware.php:55 passes it to `GateAccessResolver::resolve($path, $userId, $userRole)`. GateAccessResolver.php:21-23 grants unconditional access for `$userRole >= 4`. But `grep -rn "_SESSION\['user_role'\] =" src/` returns NO writes anywhere — login/auth code stores `$_SESSION['user_id']` and reads role from the DB (e.g. AuthMiddleware.php:200, AdminMiddleware.php:51), never `$_SESSION['user_role']`. So `$userRole` is always 0 in this path.

Suggested fix. Source the role from the authoritative place rather than a non-existent session key — e.g. look up the user row by `$_SESSION['user_id']` (as AdminMiddleware does) and pass the DB role, or have AuthMiddleware persist a validated role into the session if a cached value is desired. Cross-check the same `user_role` assumption in BaseHelpdeskAdminController.php:42 which also reads `$_SESSION['user_role'] ?? 5`.

Filed by the automated tenant-app audit and adversarially evidence-verified. Status: verified. Open — not yet actioned.


Patrick Bass
@mobieus

🚀 Jun 7, 2026 5:49am

Resolved — fixed and deployed. Commit ea9f0311e960, shipped dev-first then to all tenants on 2026-06-06.

GateMiddleware read role from non-existent $_SESSION['user_role'] (never set anywhere; AuthMiddleware validates role from DB each request without persisting it), so it always resolved to 0 and dead-ended GateAccessResolver's role>=4 admin bypass, gating admins/mods behind the paywall. Replaced with an authoritative users-table lookup by $_SESSION['user_id'] (mirroring AdminMiddleware), guarded by try/catch falling back to role 0; anonymous users skip the query. php -l passes.

Status: fixed. Thread closed and locked.


Patrick Bass
@mobieus

Log in or register to reply to this thread.