Skip to content

Harden interception and MCP capabilities - #2132

Open
xeophon wants to merge 2 commits into
mainfrom
agent/harden-interception-mcp-capabilities
Open

Harden interception and MCP capabilities#2132
xeophon wants to merge 2 commits into
mainfrom
agent/harden-interception-mcp-capabilities

Conversation

@xeophon

@xeophon xeophon commented Jul 25, 2026

Copy link
Copy Markdown
Member

Overview

Separates model inference access from rollout state access and hardens the shared MCP state bridge.

Details

  • Issues independent credentials for model inference and task-scoped state/task access.
  • Gives each framework-owned shared stateful MCP server a private service credential.
  • Replaces agent-visible shared bearer query parameters with HMAC-signed rollout-scoped state coordinates.
  • Restricts shared service credentials to /state; /task remains available only to task-scoped state credentials.
  • Preserves runtime-specific URL translation so shared Docker and remote MCP servers reach the correct interception route.

Rationale and impact

Previously, one rollout credential crossed model inference, task data, and mutable rollout state boundaries, while shared stateful MCP routes exposed their state credential to the harness. The narrower capability model keeps each component limited to the access it needs while preserving per-rollout state sharing for framework-owned tools.


Note

Medium Risk
Changes authentication boundaries for interception and shared MCP state; internal call sites are updated, but any external code unpacking the old 2-tuple Slot or relying on a single shared bearer would break.

Overview
Hardens interception and the MCP state bridge by giving model inference and rollout state separate bearer tokens, and by stopping shared-tool URLs from exposing per-rollout secrets to the harness.

Each rollout Slot is now (base_url, model_secret, state_secret). Model routes still authenticate with model_secret; /state and /task use state_secret only, so a harness API key cannot read or mutate trace state or fetch task payloads. Interception pools and per-rollout servers thread state_service_secrets from eval-level shared MCP processes; GET/PUT /state can also authorize a trusted service bearer plus X-Verifiers-State-Route (trace id) to reach the right session without the per-rollout state token.

Shared stateful MCP servers get a private VF_STATE_SECRET at eval start. Per rollout, the harness URL gains vf_state_url, vf_state_route, and an HMAC-SHA256 vf_state_signature over url+route instead of putting secrets in query strings. The server verifies signatures with hmac.compare_digest before proxying state. Task-scoped servers still receive the rollout state_secret via env for /task and direct state access.

Agent._interception_for skips reusing a long-lived owned interception server when any shared tool carries a state_secret, so rollouts get a server that knows the shared service secrets. Env.serving collects those secrets when building interception.

Reviewed by Cursor Bugbot for commit 1dbdc9d. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Harden interception and MCP state access with separate model/state credentials and HMAC-signed routing

  • Splits the interception Slot from a 2-tuple into a 3-tuple (base_url, model_secret, state_secret), giving rollouts distinct bearer tokens for model inference and state access across interception/base.py, pool.py, server.py, and rollout.py.
  • Interception servers now accept a state_service_secrets set; shared tool servers can read/write rollout state using their service secret plus an X-Verifiers-State-Route header instead of the rollout's state bearer.
  • Shared MCP server URLs now carry HMAC-SHA256-signed state coordinates (vf_state_url, vf_state_route, vf_state_signature) instead of embedding a bearer token in the query string, keeping the service secret private.
  • serve_in_runtime in mcp/launch.py always writes VF_STATE_URL and VF_STATE_SECRET to subprocess environments to prevent inheritance of stale values.
  • Risk: callers unpacking Slot as a 2-tuple will break; all internal consumers are updated but any external or third-party code depending on the old tuple shape must be updated.

Macroscope summarized 3c1df80.

Comment thread verifiers/v1/agent.py

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e9f31aef38

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread verifiers/v1/agent.py
@macroscopeapp

macroscopeapp Bot commented Jul 25, 2026

Copy link
Copy Markdown

Approvability

Verdict: Needs human review

This PR introduces security-sensitive changes to authentication flows (separating model/state capabilities, adding HMAC signature verification). Additionally, two unresolved review comments identify a potential bug where injected interceptions could cause 401 failures for shared tool state access.

No code changes detected at 3c1df80. Prior analysis still applies.

You can customize Macroscope's approvability policy. Learn more.

@xeophon
xeophon force-pushed the agent/harden-interception-mcp-capabilities branch from 1dbdc9d to 3c1df80 Compare July 27, 2026 13:25
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