Skip to content

JITSU-265: read-only MCP access and a consent warning (stacked on JITSU-264) - #1607

Merged
sahiltyagi-jitsu merged 8 commits into
newjitsufrom
fix/jitsu-265-mcp-scopes
Nov 13, 2026
Merged

sahiltyagi-jitsu merged 8 commits into
newjitsufrom
fix/jitsu-265-mcp-scopes

Conversation

@sahiltyagi-jitsu

@sahiltyagi-jitsu sahiltyagi-jitsu commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

JITSU-265 (audit finding 2, High). Part of JITSU-250. Builds on the JITSU-264 PR (it uses the key role and workspaceId), which is merged and released in console beta.110. This PR targets newjitsu; the branch needs an update from newjitsu before it merges.

Problem

MCP accepted an OAuth token or a personal API key with no scopes. Anyone can register an OAuth client under any name, and one Approve click gave the client the full account (MCP tools create and delete configs and run code).

Change

  • Consent page: the client name is labelled "chosen by the client, not verified", and a warning names the host that will receive access when the redirect URI is not loopback.
  • Read-only choice: the authorization code, refresh token and access token then carry the analyst role, so the client can read but not create, change, delete or run anything, even for an owner. It is off by default, so existing connections work as before.
  • Key scope and role on MCP: a personal API key's workspace scope and role limit also apply on MCP (before, REST only). That part lives in the JITSU-264 PR, where the limits are introduced.
  • Read-only tools only: a token whose role cannot edit can call only the tools annotated read-only (14 of the 26 tools). The other 12 return a 403: create, update and delete of resources, sync run, cancel and state reset, connector spec, stream discovery, source check, connection test, function run and profile-builder run. Before, those tools checked only workspace access, so a read-only token could, for example, delete a sync's saved state.

Verified

Each fix has tests that fail on the code before it.

  • mcp-readonly.test.ts (10 tests, real Postgres) drives the real flow: register, approve with read_only, token exchange, refresh, access token. The role survives refresh, and without the choice nothing changes. Five tests (reset_sync_state, run_sync, cancel_sync, check_source_credentials, run_function) check that a read-only token gets a 403; for the four sync tools they also check that the service is not called. They fail without the tool guard. The approving step runs as a signed-in session, because approving with an API key is refused in the JITSU-264 PR. All 10 pass on the current head.
  • A unit test for the redirect description (oauth-redirect.test.ts).
  • The consent page in headless Chromium against a local console, signed in: for a client redirecting to https://evil.example/cb the name is labelled "chosen by the client, not verified" and the warning names evil.example; for http://localhost:6274/... there is no warning. Approve with the Read-only box ticked sends read_only: true; the server returns 200 and the token exchange works. The stored refresh token has role analyst; approving without the box stores no role.

Behaviour change for API keys with the analyst role

The tool guard applies to any token whose role cannot edit, so a personal API key with role analyst is now refused the 12 non-read-only tools on MCP too, including run_sync, cancel_sync and check_source_credentials. Before, those calls checked only workspace access. REST is unchanged: the same key can still run a sync there (sources/run). The analyst role was added in the JITSU-264 PR, so keys with it have existed only since beta.110.

Rollback and rolling deploy

  • Rollback: the read-only choice is stored only as role = analyst on the connection's refresh-token row, and only this PR reads it on the OAuth path. If the console is rolled back to a build without this PR, every connection approved as read-only keeps working with no limit until the PR is deployed again.
  • Rolling deploy: while old and new pods run together, a read-only approval that is handled by an old pod (the approve request, or the token exchange within the 60 s life of the code) drops the choice, and the client then holds an unrestricted token with no error shown.

Not verified / not done

  • The rollback and rolling-deploy behaviour above is from reading the code, not from running two versions.
  • Tests call 5 of the 12 refused tools and 1 of the 14 allowed ones; nothing pins the read-only annotation list. Not covered by this PR: the user's own workspace role on the sync tools (JITSU-287).
  • Not run against a live MCP client. A read-only client also loses the probe tools (discover_streams, check_source_credentials, test_connection, run_function), which matches the consent page text.
  • MCP scopes finer than read-only, a registration allowlist, and a shorter refresh-token lifetime are product decisions.

@sahiltyagi-jitsu
sahiltyagi-jitsu marked this pull request as ready for review October 27, 2026 07:43

@jitsu-code-review jitsu-code-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review of d4919e05777240c2a7c147c1bce546a43e6643fa

Reviewed the full nine-file diff and confirmed one read-only authorization bypass. Targeted probes passed; the normal test suite was unavailable because pnpm and dependencies were absent.

@sahiltyagi-jitsu
sahiltyagi-jitsu force-pushed the fix/jitsu-265-mcp-scopes branch from d4919e0 to 67b57bf Compare October 27, 2026 12:28

@jitsu-code-review jitsu-code-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review of 67b57bfde0e565ef80b9a2b4581835a61b03514d

Reviewed the full diff and relevant authorization paths; no high-confidence new defects found. Direct redirect-helper checks passed. Vitest was unavailable because pnpm and dependencies are absent.

@jitsu-code-review jitsu-code-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review of 155b59920e35f5d7ef3cdf9d771a56e9e5f0422c

Reviewed the complete incremental diff. The only change removes an unused test import; no actionable defects found.

Anyone can register an OAuth client under any name, so the name on the
consent page proves nothing. It is now labelled as unverified, and a
warning names the host that will receive access when the redirect URI is
not loopback.

Not covered: MCP scopes, a registration allowlist and shorter refresh
token lifetime.

JITSU-265
The consent page has a read-only choice; the code, the refresh token and
the access token then carry the analyst role, so an MCP client cannot
create, change, delete or run anything even if the user is an owner.
Personal API keys used through MCP now also bring their workspace scope and
role limit (they were only enforced on the REST API). Without the choice
nothing changes.

Builds on the key scoping of JITSU-264.

JITSU-265
auth.extra is optional on AuthInfo; the CI typecheck caught it and my
local check only looked at non-test files.

JITSU-265
Sync runs, cancels, state resets, source checks and function runs were
guarded by verifyAccess only, so they ignored the token's role.
@sahiltyagi-jitsu
sahiltyagi-jitsu force-pushed the fix/jitsu-265-mcp-scopes branch from 155b599 to 2b55663 Compare October 29, 2026 07:15

@jitsu-code-review jitsu-code-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review of 2b556630d568ee0ffd32bada508688c29596c847

Reviewed the full diff and relevant authorization paths. No high-confidence defects found. Tests were not run because dependencies are unavailable.

@jitsu-code-review jitsu-code-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review of 11f1043151b7597c2588760a7ace9341231e21d8

Reviewed the full diff and relevant authorization paths. No high-confidence actionable defects found. Redirect helper checks passed; integration tests were not run because dependencies are unavailable.

jitsu-code-review[bot]
jitsu-code-review Bot previously approved these changes Nov 11, 2026

@jitsu-code-review jitsu-code-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review of 0e814864ffab5b46c4eae0217ec3cf55ea2ceb3e

Reviewed the full diff and relevant authorization paths. No high-confidence actionable defects found. Redirect helper checks passed; integration tests were not run because dependencies are absent.

Base automatically changed from fix/jitsu-264-api-key-scoping to newjitsu November 12, 2026 12:17

@jitsu-code-review jitsu-code-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review of 9516ca00183f38226fb9fc87f9aca9fa435d613b

Reviewed the full diff and relevant authorization paths. No high-confidence actionable defects found. Redirect helper assertions passed; full test suites were unavailable because dependencies are not installed.

@sahiltyagi-jitsu sahiltyagi-jitsu added the deploy:console Auto-deploy console to beta when this PR merges (JITSU-68) label Nov 13, 2026
@sahiltyagi-jitsu
sahiltyagi-jitsu merged commit cc8b614 into newjitsu Nov 13, 2026
14 checks passed
@sahiltyagi-jitsu
sahiltyagi-jitsu deleted the fix/jitsu-265-mcp-scopes branch November 13, 2026 03:13
@github-actions

Copy link
Copy Markdown
Contributor

🚀 deploy:console label detected — triggered a beta console deployment to jitsu-cloud-infra. Track it in the deploy runs (newest at top): https://github.com/jitsucom/jitsu-cloud-infra/actions/workflows/deploy.yaml?query=event%3Aworkflow_dispatch

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

Labels

deploy:console Auto-deploy console to beta when this PR merges (JITSU-68)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant