fix(security): prevent cross-org KV data leak for multi-org users#4018
Merged
Conversation
The legacy unscoped `/api/kv/:key` routes lacked `resolveOrgFromPath` middleware. Combined with a `.executeTakeFirst()` fallback (no ORDER BY) in the MCP OAuth org-resolution path, multi-org users without an `x-org-id` header could non-deterministically read/write KV data from the wrong organization. Two changes: 1. Remove the legacy `/api/kv/:key` mount — the org-scoped version at `/api/:org/kv/:key` already exists and is properly guarded. 2. In the MCP OAuth fallback (context-factory.ts), when no org hint is provided, only resolve the org when the user has exactly one membership. Multi-org users without a hint now get `organization: undefined` instead of a random pick. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
7fcb429 to
be14453
Compare
pedrofrxncx
approved these changes
Jun 22, 2026
decocms Bot
pushed a commit
that referenced
this pull request
Jun 22, 2026
PR: #4018 fix(security): prevent cross-org KV data leak for multi-org users Bump type: patch - decocms (apps/mesh/package.json): 3.37.1 -> 3.37.2 Deploy-Scope: server
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
/api/kv/:keyroutes — these lackedresolveOrgFromPathmiddleware, so org context was resolved via the MCP OAuth fallback path which uses.executeTakeFirst()withoutORDER BY. For multi-org users without anx-org-idheader, PostgreSQL could return any membership row, causing reads/writes to land in the wrong org's KV namespace. The org-scoped version at/api/:org/kv/:key(mounted inorg-scoped.tswith proper middleware) already exists and is unaffected.x-org-id/x-org-slugheader is provided, the fallback now only resolves an org when the user has exactly one membership. Multi-org users without a hint getorganization: undefined(resulting in a 400 "Organization required" from any org-scoped endpoint) instead of a non-deterministic pick.Files changed
apps/mesh/src/api/app.ts/api/kv/:keymount and unused importapps/mesh/src/core/context-factory.ts.executeTakeFirst()withlimit(2).execute()— return the row only when exactly 1 membership existsTest plan
bun run check— passes (no type errors)bun run fmt— passesbun run lint— passes (0 errors)bun test apps/mesh/src/core/— 57 pass, 4 fail (pre-existing integration test failures on main due to no local PostgreSQL)GET /api/kv/:keyreturns 404 (route removed)GET /api/:org/kv/:keyworks correctly withresolveOrgFromPathx-org-idheader getsorganization: undefined→ 400 on org-scoped endpoints🤖 Generated with Claude Code
Summary by cubic
Prevents cross‑org KV access for multi‑org users by removing the unscoped
/api/kv/:keyand hardening MCP OAuth org resolution. KV is now org‑scoped only; multi‑org requests without an org hint return 400, and removed users no longer get SSO sessions.Bug Fixes
/callbackbefore creating a session; redirect withsso_error=not_a_memberif not a member.Migration
/api/kv/:keywith/api/:org/kv/:key.x-org-idorx-org-slug; otherwise org‑scoped endpoints return 400.Written for commit be14453. Summary will update on new commits.