Skip to content

Pending chat state: bind to user_id, fail closed when session_id omitted #30

@mwtcmi

Description

@mwtcmi

Problem

Tools/ChatParser.php getPending/setPending/clearPending key only on the request-supplied session_id:

  • getPending queries oc_sessions with WHERE id = ? (no user_id)
  • setPending INSERTs with user_id = NULL explicitly
  • clearPending clears by id only

Frogman.class.php::handleChatRequest() reads session_id from the POST body verbatim and falls back to the literal string 'chat-default' when absent.

Two consequences:

  1. chat-default shared bucket — two ad-hoc API callers that both omit session_id collide on the same pending state. Last writer wins on confirm/cancel. Footgun.
  2. No user_id binding on pending rows — even with explicit session_ids, the row that holds the queued tool + params is keyed solely on session_id.

Why this is LOW (not GHSA)

The realistic attack chain ends up as self-confused-deputy at most:

  • The caller doing the "yes" must already be authenticated.
  • runTool() uses the calling user's authContext, so the permission check is against the would-be attacker, not the original queuer — the attacker can only execute tools they're already authorized for.
  • The audit row attributes to the attacker; no identity laundering.

So the "gain" is "execute under your own audit identity an action you could already execute under your own audit identity." Not an escalation. The genuine concern is the shared-bucket footgun.

Fix

Two changes, either alone closes the footgun:

  1. Fail closed on missing session_id — return 400 if the body doesn't supply one, instead of defaulting to chat-default.
  2. Bind pending rows to user_id — store the calling user's id in oc_sessions.user_id on setPending, and add AND user_id = ? to getPending/clearPending.

Files

  • Tools/ChatParser.php:19-48 (getPending/setPending/clearPending)
  • Frogman.class.php:230 (the 'chat-default' fallback)

Discovered

Internal security audit, 2026-05-18.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions