fix(pods): stop leaking other users' private DMs into admin sidebars#375
Merged
Conversation
`getAllPods` and `getPodsByType` were bypassing the membership filter for global admins. The intent was a moderation view; the effect was that admins (e.g. the xcjsam dev account) saw every agent-room and agent-dm in the instance in their default sidebar — including 1:1 DMs other users had with their installed agents. Clicking one of those rows looked like "Talk to" was navigating to a stranger's DM, and posting failed with "Not authorized to post in this pod" because the pod-message route correctly checks membership. Three changes: 1. `getAllPods`: default `scope=mine` now filters to caller membership for everyone, admins included. `?scope=all` is a separate admin- only opt-in for moderation tooling; non-admins are silently downgraded to `scope=mine`. 2. `getPodsByType`: personal pod types (agent-room, agent-dm, agent-admin) are always filtered to caller membership — the instance-wide audit is a separate admin tool, not this generic listing. 3. `getPodById`: add a membership gate for personal pod types and 404 non-members. The route previously returned the full pod payload to anyone authenticated, which leaked existence and membership of every private DM by direct ID lookup. Unit tests rewritten to encode the corrected invariant + cover the new `scope=all` admin path and the `getPodById` 404 case.
lilyshen0722
added a commit
that referenced
this pull request
May 15, 2026
Adds a new bullet under Agent Runtime — Quick Rules covering the membership-by-default gate on the sidebar / listing / direct-ID surfaces (admins do NOT bypass; ?scope=all is the admin opt-in) and the canViewPod gate that pod-scoped read endpoints must call before returning content. Mirrors the pod-manager skill update in commonly-skills@e2ae064.
3 tasks
samxu01
added a commit
that referenced
this pull request
May 16, 2026
PR #375 made getPodById 404 non-members of all personal pod types to prevent admins accidentally landing in other users' DMs via the sidebar. That broke V2 inspector's a2a DM navigation — the /v2/pods/<id> layout 404'd even though canViewPod (used by /api/messages, /api/posts, etc.) allows §3.7 fan-out viewers. Carve-out: - agent-dm: defers to canViewPod (admins + §3.7 fan-out) - agent-room: strict membership (1:1 user↔agent) - agent-admin: strict membership (ops surface) Frontend already renders an isReadOnly banner in place of the composer for non-member viewers. 20/20 podController tests pass (3 new). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
GET /api/podsandGET /api/pods/:typeno longer bypass membership filter for admins on the default sidebar listingGET /api/pods/:idnow returns 404 for personal pod types (agent-room / agent-dm / agent-admin) when caller is not a member?scope=allbecomes an explicit admin-only opt-in for moderation tooling; non-admins silently downgrade toscope=mineWhy
Reproduced as xcjsam (global admin) on app-dev: sidebar showed 82 pods, including sam-demo's 1:1 agent-rooms with Nova/Pixel/Cody. Clicking any of them looked like "Talk to" was navigating into a stranger's DM. Post fails with
Not authorized to post in this pod(correct), so the user experience was "I clicked Talk-to and now I can't chat." The real bug was upstream: the pod listing should never have surfaced other users' personal DMs.POST /api/agents/runtime/roomitself was correct — it creates a fresh(agentUser, caller)room and the message route correctly gates posting on membership. The leak was purely in the read side.Test plan
backend/__tests__/unit/controllers/podController.test.js— 17/17 passing (4 new cases: admin filter on default scope, scope=all admin pass-through, scope=all non-admin downgrade, getPodById 404)GET /api/podsreturns only xcjsam's pods (not 82), and thatGET /api/pods/<sam-demo's agent-room id>returns 404