Skip to content

fix(agent): authenticate platform MCP tools with the run invocation credential - #4487

Merged
kwakayama merged 1 commit into
mainfrom
fix/1327-platform-tools-run-credential
Sep 12, 2026
Merged

kwakayama merged 1 commit into
mainfrom
fix/1327-platform-tools-run-credential

Conversation

@kwakayama

@kwakayama kwakayama commented Sep 12, 2026 •

Copy link
Copy Markdown
Contributor

Problem

Hosted agent runs can read project files but cannot write them: every create_file/update_file/delete_file from a schedule-fired or control-plane-verified run fails with [authorization-denied] Access denied, while get_file/list_files succeed. This silently breaks every template that persists records from agents (verified live on agentic-inbox-processing-outlook; agentic-job-submission-processing last wrote successfully on 2026-09-02, before the current runtime rollout).

Full analysis: veryfront/veryfront-issue-inbox#1327

Root cause

Since #4214 the hosted agent-stream path hands withVeryfrontPlatformRemoteTools the projectRuntimeToken (ctx.proxyToken) — the stream credential signed with RUNTIME_SCOPES.runsStream, which carries files:read but no files:write. The run invocation credential minted expressly for platform tool callbacks (mintRuntimeInvocationAuthToken → runsExecute, which does carry files:write) arrives as payload.credentials.authToken but only reached framework API calls, never the MCP tool source. veryfront-api's scope ladder then correctly denies the write.

Fix

Pass the verified request credential (apiAuthToken) to the framework-owned platform MCP tool source. Project-code-visible surfaces are unchanged and keep the runtime's project credential: the agent environment (VERYFRONT_API_TOKEN env var), the sandbox (projectAgentSandbox.authToken), and Studio remote tools. This preserves #4214's isolation intent — project code and sandbox never see the run credential — while restoring the authority the invocation credential exists to provide ("The runtime calls integration tools back through the platform with this token").

apiAuthToken already falls back to ctx.proxyToken when the payload carries no credential, so behavior for token-less requests is unchanged.

Red/green

The existing tests pinned the regressed routing. Red: flipping the platform-MCP authorization assertions to expect the request credential fails on main (3 tests: control-plane stream config, legacy stream policy identities, credential isolation). Green: the one-line token routing change. The isolation test's environment assertion (VERYFRONT_API_TOKEN: "run-scoped-token") still passes untouched, demonstrating the env boundary holds.

deno task test:file src/server/handlers/request/agent-stream.handler.test.ts — 3 passed (67 steps), 0 failed. deno check + deno lint + deno fmt --check clean on touched files.

https://claude.ai/code/session_019B9SYdGjpN6sQ4424NLv91

Summary by CodeRabbit

  • Bug Fixes
    • Platform MCP requests now authenticate with the verified run invocation credential, improving authorization for platform tool callbacks.
    • Project-code-visible surfaces continue using the runtime’s project credential.
    • Updated request-handling tests to reflect the corrected authentication behavior.

…redential

Hosted agent runs could read project files but every create_file failed
with authorization-denied: the platform MCP tool source authenticated
with the stream credential (runsStream scopes, no files:write) instead
of the run invocation credential minted for platform tool callbacks
(runsExecute, which carries files:write). Route the verified request
credential to the framework-owned platform MCP source while
project-code-visible surfaces (agent environment, sandbox) keep the
runtime's project credential, preserving the isolation contract of
veryfront-issue-inbox#4214.

Fixes veryfront-issue-inbox#1327.

Claude-Session: https://claude.ai/code/session_019B9SYdGjpN6sQ4424NLv91

@greptile-apps greptile-apps 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.

Your trial has ended. Reactivate Greptile to resume code reviews.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 12, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-12T12:37:08.453416Z c516dd2 PR opened
🔒 Security Review ✅ Completed 2026-09-12T12:40:58.573872Z c516dd2 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@coderabbitai

coderabbitai Bot commented Sep 12, 2026 •

Copy link
Copy Markdown

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Advanced

Run ID: 1ad8588f-937f-4a0a-b38b-3ee554f06a9f

📥 Commits

Reviewing files that changed from the base of the PR and between f5a8248 and c516dd2.

📒 Files selected for processing (2)
  • src/server/handlers/request/agent-stream.handler.test.ts
  • src/server/handlers/request/agent-stream.handler.ts

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The agent stream now passes the verified run invocation credential to the platform MCP source. Tests now expect platform MCP requests to use the request-scoped user token.

Changes

Platform MCP authentication

Layer / File(s) Summary
Use the verified invocation credential
src/server/handlers/request/agent-stream.handler.ts
withVeryfrontPlatformRemoteTools now receives apiAuthToken, and the credential scope requirements are documented.
Update authentication assertions
src/server/handlers/request/agent-stream.handler.test.ts
Platform MCP request tests now expect Bearer request-scoped-user-token.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Merge Risk: ⚪ Minimal · up to c516d

The credential-routing change is consistent with the tested platform and Studio authentication contracts and is mergeable.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: platform MCP tools now authenticate with the run invocation credential.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 2…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/1327-platform-tools-run-credential

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown

📦 Client bundle boundary

Entrypoint Modules Source size Server leaks
src/index.client.ts 289 2307 KiB ✅ 0

A server module in a client graph aborts hydration in the browser. New leaks fail CI; known leaks are tracked in scripts/lint/client-bundle-baseline.json to burn down.

@gitar-bot

gitar-bot Bot commented Sep 12, 2026

Copy link
Copy Markdown

Important

You are using the Gitar free plan. Upgrade to unlock code review, CI analysis, auto-apply, custom automations, and more.

Gitar

Copy link
Copy Markdown
Contributor Author

Automated Code Review

Score: 88/100 — Good: a tight, well-reasoned fix for a real authz bug, with the isolation boundary it depends on independently verified by tests.

Strengths

  • Minimal, targeted diff: exactly one production line changed (token: projectRuntimeToken → token: apiAuthToken at agent-stream.handler.ts:1199), scoped to the single call site of withVeryfrontPlatformRemoteTools. No other consumer of projectRuntimeToken (agent env vars, projectAgentSandbox.authToken, Studio remote tools) was touched, which is exactly what's needed to preserve the fix: isolate user credentials from project agent execution #4214 isolation contract.
  • Root cause is well-explained and checks out: I traced apiAuthToken (payload.credentials?.authToken || ctx.proxyToken || "", line 1023) vs projectRuntimeToken (ctx.proxyToken || "", line 1038) — they're genuinely different credentials, and only the platform MCP source (a framework-internal fetch to ${apiUrl}/mcp, never surfaced to project code) now gets the former.
  • The isolation invariant is tested, not just asserted in prose: the "keeps request-scoped credentials out of project agent environments" test confirms VERYFRONT_API_TOKEN in the agent env still resolves to the project token while the platform MCP request now correctly carries the new credential — this is the test that actually matters for the security claim in the PR body, and it passes.
  • Good code comments: the added block at agent-stream.handler.ts:1033-1037 clearly documents why the platform MCP source gets different treatment than sandbox/env, which will save the next reader from re-deriving this.
  • Red/green discipline: PR body documents the failing-on-main assertions and the passing fix, which is easy to verify against the diff (3 hunks in the test file, all flipping the expected bearer token for /mcp calls).

Minor concerns (non-blocking)

  • No new test exercises the actual previously-broken path (create_file succeeding end-to-end); the fix is validated via header/token assertions rather than a scoped-permission simulation. Given the test harness's mocked fetch, this may not be practical here, but worth confirming against a real files:write-scoped token in staging before/after rollout.
  • The fallback semantics (apiAuthToken falling back to ctx.proxyToken when the payload has no credential) are correct but mean any upstream bug in how veryfront-api mints/attaches payload.credentials.authToken would silently degrade back to the old (broken-for-writes) behavior rather than fail loudly — that dependency lives outside this repo, so just flagging it as an integration risk to confirm once deployed.
  • Test token naming ("request-scoped-user-token") reads as if it's the raw end-user token; the PR body clarifies it's actually the minted run-invocation credential (runsExecute scope). A rename to something like "run-invocation-token" would make the test intent match the PR's own terminology, but this is cosmetic.
  • CI was still running several checks (coverage shards, lint, JS/TS CodeQL) at review time — worth confirming full green before merge, though typecheck, format, and test-layout already passed.

Overall: sound, narrowly-scoped security fix with the right test backing its central claim.


Generated by Claude Code

@kwakayama
kwakayama enabled auto-merge September 12, 2026 12:41
@codecov

codecov Bot commented Sep 12, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@sonarqubecloud

Copy link
Copy Markdown

@kwakayama
kwakayama added this pull request to the merge queue Sep 12, 2026
Merged via the queue into main with commit 4848159 Sep 12, 2026
68 checks passed
@kwakayama
kwakayama deleted the fix/1327-platform-tools-run-credential branch September 12, 2026 13:31
@kojiwakayama kojiwakayama mentioned this pull request Sep 16, 2026
3 tasks
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.

2 participants