"Deny" on a pending knock request has no error handling and can be shown to users who lack kick power #49

Closed
opened 2026-09-12 01:51:13 -04:00 by jared · 0 comments
Owner

Severity: medium · Type: bug · Confidence: high

Location: src/app/features/room/MembersDrawer.tsx:241-245, 459-479, src/app/hooks/usePendingKnocks.ts:26-31

Problem

The "Pending Requests" section (and the identical gating logic duplicated inline in MembersDrawer.tsx) is shown only when myPowerLevel >= invitePowerLevel. "Approve" uses mx.invite (correctly gated by invite power), but "Deny" calls mx.kick, which requires the room's kick power level, not invite power. In rooms where kick PL is set higher than invite PL (a legitimate, not-uncommon configuration — e.g. moderators can invite but only admins can kick), a moderator sees the Deny button, clicks it, and the server rejects the request with M_FORBIDDEN. Neither mx.invite(...) nor mx.kick(...) here has a .catch or any error surface (no toast, no disabled/loading state), so the click appears to do nothing and the request stays in the pending list with no feedback that it failed, an unhandled promise rejection results.

How to trigger

In a room where kick power level > invite power level, have a user with power between those two thresholds try to deny a knock. The call fails silently.

Suggested fix

Gate the Deny button on kick power level (or hide/disable it separately from Approve), and add .catch handlers on both mx.invite and mx.kick here that surface a toast on failure (consistent with notifyTagFailure pattern elsewhere in the code).


Filed from the September 2026 client audit (branch lotus @ 4bea4895).

**Severity:** medium · **Type:** bug · **Confidence:** high **Location:** `src/app/features/room/MembersDrawer.tsx:241-245, 459-479`, `src/app/hooks/usePendingKnocks.ts:26-31` ### Problem The "Pending Requests" section (and the identical gating logic duplicated inline in `MembersDrawer.tsx`) is shown only when `myPowerLevel >= invitePowerLevel`. "Approve" uses `mx.invite` (correctly gated by invite power), but "Deny" calls `mx.kick`, which requires the room's *kick* power level, not invite power. In rooms where `kick` PL is set higher than `invite` PL (a legitimate, not-uncommon configuration — e.g. moderators can invite but only admins can kick), a moderator sees the Deny button, clicks it, and the server rejects the request with `M_FORBIDDEN`. Neither `mx.invite(...)` nor `mx.kick(...)` here has a `.catch` or any error surface (no toast, no disabled/loading state), so the click appears to do nothing and the request stays in the pending list with no feedback that it failed, an unhandled promise rejection results. ### How to trigger In a room where `kick` power level > `invite` power level, have a user with power between those two thresholds try to deny a knock. The call fails silently. ### Suggested fix Gate the Deny button on kick power level (or hide/disable it separately from Approve), and add `.catch` handlers on both `mx.invite` and `mx.kick` here that surface a toast on failure (consistent with `notifyTagFailure` pattern elsewhere in the code). --- --- _Filed from the September 2026 client audit (branch `lotus` @ 4bea4895)._
jared added this to the Audit 2026-09 · Medium & Low milestone 2026-09-12 01:51:13 -04:00
jared added the bugpriority: mediumarea: moderation labels 2026-09-12 01:51:13 -04:00
jared self-assigned this 2026-09-12 01:51:13 -04:00
jared closed this issue 2026-09-12 20:29:09 -04:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
2026-11-14
Dependencies

No dependencies set.

Reference: LotusGuild/cinny#49