Skip to content

Subscriptions without a session_id filter observe every session's envelopes #45

@nficano

Description

@nficano

src/Internal/Runtime/SubscriptionRouter.php:74 only authorizes the subscription filter when the caller explicitly supplied a session_id constraint. If $msg->filter['session_id'] is not set the function returns true, the subscription compiles with sessionIds: [], and src/Runtime/Subscription.php:30 treats an empty sessionIds list as "match every session" because of the early-return guard if ($this->filter->sessionIds !== [] && ...). Combined with SubscriptionManager::dispatch() in src/Runtime/SubscriptionManager.php:70, this means any authenticated peer can send Subscribe({}) (or any filter that omits session_id) and receive a live fan-out of every envelope the runtime emits for every other session — telemetry, prompts, tool inputs, lease grants, and error payloads.

The existing integration coverage at tests/Integration/SubscriptionTest.php:88 only checks that a peer cannot subscribe with an explicit foreign session_id, so the bypass through the empty-filter form is unguarded by tests. docs/recipes.md and the README pitch subscriptions as the session-scoped tail of a job a CLI submitted, not as a global listener, so the privilege gap also contradicts the documented behavior.

Fix prompt: In SubscriptionRouter::authorizeFilter(), default the filter's session_id to the requesting session's id when the field is unset or evaluates to an empty constraint, rather than waving the request through. Alternatively, require the requester to be explicit and reject Subscribe envelopes that have no session_id filter unless the principal carries an admin capability. Add an integration test that opens session A and session B against the same runtime, has B emit events, and verifies a Subscribe({}) on A never receives B's envelopes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingseverity:highHigh severity

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions