Forums Bug Reports Thread

Missing privilege-ceiling check on moderator warn action — a moderator can target a higher-privileged account

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

Area: Admin deep-dive (trust/safety) (audit p15a) · Surface: POST /admin/moderation/{id}/warn (AdminModerationController@warn) · Dimension: security · Severity: minor

A role-3 moderator can issue a formal warning (warning email + permanent internal mod note recorded against the account, report marked in_progress) against an administrator or super-admin via a report. The impact is low — it does not change the target's state or sessions — but it is inconsistent with the documented peer-tier privilege ceiling enforced on every other enforcement action in this controller and lets a moderator attach mod-log noise to a higher-tier account. OWASP A01 Broken Access Control (missing function-level authorization consistency).

Evidence

AdminModerationController.php:190-255: warn() does requireRole(3) and a self-target guard (line 203 `if ((int) $reported['id'] === (int) $actor['id'])`), but unlike suspend()/ban()/shadowBan() in the same controller it never checks `$reported['role'] > $actor['role']`. Compare suspend() at line 284 (`if ((int) $reported['role'] > (int) $actor['role']) { ... Cannot suspend a user above your role level }`) which is absent from warn().

Suggested fix. Add the same ceiling guard used in suspend()/ban() to warn(): after loading $reported, `if ((int) $reported['role'] > (int) $actor['role']) { flash error + redirect; }` (or call assertCanModify()).

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.

Added the privilege-ceiling guard to warn() matching suspend()/ban(): after loading $reported (via User::findById, which carries the role column), if (int)$reported['role'] > (int)$actor['role'] it flashes 'Cannot warn a user above your role level.' and redirects to /admin/moderation/{reportId}. Placed right after the self-action guard, before the warn message is composed, so a moderator can no longer warn an above-tier user.

Status: fixed. Thread closed and locked.


Patrick Bass
@mobieus

Log in or register to reply to this thread.