Forums Bug Reports Thread

Privilege escalation: a self-service forum owner (role 2) can promote any user to global site-Moderator (role 3)

Patrick Bass · Jun 6 · 19 · 1 Locked
[Critical] [Urgent] [Bug Fixed] [Always Reproduces]
🚀 OP Jun 6, 2026 8:51pm

Area: Forums (re-run) (audit p2r) · Surface: POST /forums/{slug}/moderators/add (ForumController@addSubModerator) · Dimension: Security (OWASP) · Severity: critical

Forum ownership is an unprivileged, self-service capability (any registered user can create a community forum). The owner-controlled addSubModerator path side-effects a GLOBAL role promotion (Registered 2 → Moderator 3) via upgradeRoleIfNeeded. Role 3 is the site-wide Moderator tier that AdminMiddleware lets into the admin/moderation plane. A low-privilege user thus controls who becomes a site moderator — a broken-access-control / privilege-escalation chain (OWASP A01:2021). The admin path (AdminForumController@addModerator, requireRole(4)) calling the same helper is fine because an admin is trusted; the unprivileged-owner path is not.

Evidence

ForumController::storeForum (platform/src/Controllers/ForumController.php:3592-3667) lets ANY authenticated user create a community forum and makes them its owner: `ForumModerator::assign($forumId, (int) $user['id'], 'owner');` — no role gate beyond requireAuth(). addSubModerator (line 3738-3776) is gated ONLY on owner-or-admin: `$isOwner = ForumModerator::isOwner(...); if (!$isOwner && (int) $user['role'] < 4) { ... permission denied }` then `ForumModerator::assign(...); ForumModerator::upgradeRoleIfNeeded((int) $target['id']);`. upgradeRoleIfNeeded (platform/src/Models/ForumModerator.php:96-104) does `if ((int) $user['role'] !== 2) return; User::update($userId, ['role' => 3], true);` — it bumps the target's GLOBAL site role to 3. AdminMiddleware (platform/src/Middleware/AdminMiddleware.php:56) admits `role >= 3`, and dozens of admin/moderation routes use requireRole(3). So: register → create a community forum (free) → add any victim as sub-mod → victim is now a site-wide Moderator with admin-panel + moderation-queue access across the whole tenant.

Suggested fix. Per-forum sub-moderators granted by a non-admin owner must NOT receive a global role bump. Either: (a) skip upgradeRoleIfNeeded entirely in addSubModerator and represent forum-mod authority purely via the forum_moderators row (hasModAuthority already consults that table), or (b) restrict global-role promotion to assignments made by an actor with role >= 4. Keep upgradeRoleIfNeeded only on the admin-initiated path.

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


Patrick Bass
@mobieus

🚀 Jun 6, 2026 9:00pm

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

ForumController::addSubModerator now triggers the global users.role 2->3 promotion (ForumModerator::upgradeRoleIfNeeded) only when the acting user is an admin (role>=4). A non-admin forum owner can still grant forum-scoped sub-moderator authority via the forum_moderators row, but can no longer escalate an arbitrary user to site-wide Moderator (admin-plane access). The identical sibling path - resigning and appointing a successor owner (/forums/{slug}/resign) - was guarded the same way in the same change.

Status: fixed. Thread closed and locked.


Patrick Bass
@mobieus

Log in or register to reply to this thread.