Forums Bug Reports Thread

mobieusGate write_gated mode is a no-op — paywall never blocks any write

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

Area: Cross-cutting infra (audit p14) · Surface: GateMiddleware / mobieusGate paywall (POST writes on gated surfaces) · Dimension: security · Severity: major

OWASP A01 Broken Access Control. When an operator configures a gated surface in 'write_gated' mode (read free, writes require a paid mobieusGate subscription), GateMiddleware sets a flag `$_REQUEST['_gate_write_blocked'] = true` and then returns, allowing the request to proceed to the controller. No controller, model, or service ever reads that flag. The result is that a non-subscribed (or anonymous-with-session) user can perform every write action on a 'write_gated' surface — post threads/replies, edit, etc. — completely bypassing the paywall the operator believes is enforced. The middleware silently degrades a paid access-control gate into a no-op.

Evidence

platform/src/Middleware/GateMiddleware.php:68-71 — `if ($result['mode'] === 'write_gated') { $_REQUEST['_gate_write_blocked'] = true; return; }`. Grepping the whole tree: `grep -rn "_gate_write_blocked" src/` returns ONLY the write site in GateMiddleware.php:69 — there is no consumer anywhere. GateAccessResolver.php:33 sets `$result['mode'] = $mode` where mode comes from `GateSurfaceConfig::getMode(...)`, so `write_gated` is a real, operator-selectable surface mode.

Suggested fix. Either enforce the block in the middleware (for state-changing methods POST/PUT/PATCH/DELETE on a write_gated surface, render the paywall / return 402 like read_gated does, instead of just setting a flag), or have BaseController (or each write handler) consume `$_REQUEST['_gate_write_blocked']` and abort with 402. Add a regression test that a non-subscriber POST to a write_gated forum is rejected.

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


Patrick Bass
@mobieus

🚀 Jun 7, 2026 5:25am

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

write_gated surfaces no longer just set $_REQUEST['_gate_write_blocked'] (which nothing consumed). For state-changing methods (POST/PUT/PATCH/DELETE) the middleware now enforces the block by rendering the paywall and exiting (402 + X-Gate header) like read_gated; non-state-changing reads still pass through. The flag is kept set for any defensive downstream consumer.

Status: fixed. Thread closed and locked.


Patrick Bass
@mobieus

Log in or register to reply to this thread.