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