Forums Bug Reports Thread

Revision history page leaks pending/rejected revisions and moderator reject reasons to anonymous users

Patrick Bass · Jun 6 · 10 · 1 Locked
[Major] [High Priority] [Bug Fixed] [Always Reproduces]
🚀 OP Jun 6, 2026 6:11pm

Area: mobieusKnow (audit p6) · Surface: GET /know/{slug}/history (KnowledgeController@history) · Dimension: security · Severity: major

OWASP A01:2021 Broken Access Control / sensitive information disclosure. The reject reason is authored by a moderator and may name the submitter, quote the offending content, or describe internal policy. Both the existence and the metadata of pending/rejected revisions are exposed publicly, complementing finding #1 (which leaks the bodies). Combined, an anonymous user gets the full moderation trail.

Evidence

history() (KnowledgeController.php:252-269) has no requireAuth and is in the public route group (routes.php:589). It calls KnowledgeRevision::forPage() which returns EVERY status: `WHERE kr.page_id = :pid ORDER BY kr.id DESC` with no status filter (KnowledgeRevision.php:43-54). history.php renders all of them including the status badge and the moderator's free-text rejection note: line 64 `<?= $e(str_replace('_', ' ', $rev['status'])) ?>` and lines 72-75 `<?php if (!empty($rev['reject_reason'])): ?> Rejected: <?= $e($rev['reject_reason']) ?>`. The `isMod` flag (history.php:13) only gates the Restore button, not visibility of pending/rejected rows.

Suggested fix. Filter forPage() to approved/rolled_back for non-moderators (pass a viewer-is-mod flag, or add forPagePublic()). Hide reject_reason and pending/rejected rows from non-moderators in history.php.

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


Patrick Bass
@mobieus

🚀 Jun 7, 2026 4:59am

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

Controller-side fix confirmed already present and correct: history() computes viewer-is-mod ($isMod) and filters forPage() results to approved/rolled_back for non-moderators (lines 262-267), and historyRevision() 404s non-mods on non-approved revision ids (lines 309-311). pending/rejected bodies and reject_reason never reach non-moderators. No additional controller change required.

Status: fixed. Thread closed and locked.


Patrick Bass
@mobieus

Log in or register to reply to this thread.