security(gateway): scope /resume and /sessions to the caller's origin (IDOR)
/resume resolved a persisted session id/title with no ownership check on any adapter except Matrix, so an authorized caller could bind their gateway session to another user's/room's transcript and read it. The titled-session listing and numeric index were also globally enumerable on non-Matrix platforms, exposing the ids and previews needed to target the IDOR. Generalize the Matrix-only room guard to an adapter-agnostic ownership check (live origin when active; DB row source + user_id for persisted-only sessions, the only fields available), applied to the direct-id/title path and the listing/numeric paths on every platform. An explicit admin --all override is honored. The Matrix path is preserved unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -239,6 +239,7 @@ gateway:
|
||||
matrix_blocked_no_origin: "⚠️ Matrix /resume blocked: this named session has no recorded room origin, so Hermes will not resume it inside the current room by default. Use `/resume --cross-room {name}` if you intentionally want to cross room boundaries."
|
||||
matrix_blocked_other_room: "⚠️ Matrix /resume blocked: that session belongs to a different Matrix room ({room}). Use `/resume --cross-room {name}` if you intentionally want to resume it here."
|
||||
matrix_cross_room_success: "⚠️ Cross-room resume: resumed **{title}** inside Matrix room **{room}**.\nFuture messages in this room will use that transcript until `/reset` or another `/resume`.{msg_part}"
|
||||
blocked_not_owner: "⚠️ /resume blocked: '**{name}**' belongs to a different user or chat. You can only resume sessions from this chat."
|
||||
no_named_sessions: "No named sessions found.\nUse `/title My Session` to name your current session, then `/resume My Session` to return to it later."
|
||||
list_header: "📋 **Named Sessions**\n"
|
||||
list_item: "• **{title}**{preview_part}"
|
||||
|
||||
Reference in New Issue
Block a user