Skip to content

Clamp remote source overrides#1372

Open
jlfetter1 wants to merge 2 commits into
garrytan:masterfrom
Techtrisdev:techtris/stage0-source-scope
Open

Clamp remote source overrides#1372
jlfetter1 wants to merge 2 commits into
garrytan:masterfrom
Techtrisdev:techtris/stage0-source-scope

Conversation

@jlfetter1
Copy link
Copy Markdown

Summary

Fixes the OAuth source-scope bypass reported in #1371.

This PR treats remote source_id tool parameters as requests, not authority. For remote MCP callers, source selection is now clamped to the caller's OAuth allowedSources / sourceId claims at tool invocation time.

Changes

  • Clamp remote query.source_id to the caller's allowed source set.
  • Reject unauthorized explicit source requests with permission_denied instead of returning empty success.
  • Clamp remote source_id=__all__ to the caller's allowed sources.
  • Add safe explicit get_page.source_id selection for allowed shared/canonical sources.
  • Reject ambiguous get_page source_id=__all__.
  • Thread source scope through think gather.
  • Apply source filters to searchTakes / searchTakesVector in Postgres and PGLite implementations.
  • Add source-scope audit metadata to HTTP MCP request logs without logging query text or page bodies.
  • Add focused PGLite regression coverage for unauthorized source override, clamped __all__, explicit shared get_page, unauthorized get_page, and think source scoping.

Security framing

The issue maps to CWE-285 Improper Authorization, with related CWE-266 and CWE-20 concerns. It also matches Bishop Fox's LLM testing pattern "Authorization Bypass through User Controlled Parameter." In this case, source_id is authority-bearing and must be validated server-side against token claims.

Verification

Executed locally in the fork worktree:

npm exec --yes bun -- test test/e2e/source-isolation-pglite.test.ts

Result: 19 passed, 0 failed.

npm exec --yes bun -- run typecheck

Result: passed.

Also live-tested in a downstream OAuth deployment with synthetic canary pages: unauthorized query.source_id no longer leaked cross-source content, source_id=__all__ clamped to allowed sources, explicit get_page source_id=shared worked, and source-scope audit rows were written.

No sensitive data was used in the reproduction or verification.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant