fix(security): set strictMcpConfig to block cloned-PR .mcp.json auto-load#210
Conversation
…load settingSources:[] (issue #191) gates settings.json/CLAUDE.md but not a project .mcp.json, which the CLI auto-discovers from cwd by default. With cwd = the cloned PR tree under bypassPermissions, a hostile .mcp.json could register a stdio MCP server whose command runs on connect, the same RCE primitive class as #191. strictMcpConfig:true emits --strict-mcp-config, restricting MCP loading to the explicitly-injected mcpServers. Closes #196 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughThis PR hardens MCP (Model Context Protocol) server discovery in ChangesMCP Configuration Hardening
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related issues
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
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. Comment |
There was a problem hiding this comment.
Pull request overview
This PR hardens the Claude Agent SDK invocation against hostile MCP auto-discovery from an attacker-controlled cloned PR working directory by forcing MCP loading to only the explicitly injected mcpServers set.
Changes:
- Set
strictMcpConfig: truein the Agent SDKqueryOptionsto suppress project.mcp.jsonauto-discovery. - Add a regression test asserting
strictMcpConfigis enabled while preservingmcpServersforwarding and the existingsettingSources: []pin.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
src/core/executor.ts |
Pins strictMcpConfig: true alongside settingSources: [] to prevent cloned-tree .mcp.json auto-load. |
test/core/executor.test.ts |
Adds a regression test ensuring strictMcpConfig is set and mcpServers/settingSources are preserved. |
What
Closes #196. Follow-up to #191 / PR #195. That PR pinned
settingSources: []to close the.claude/settings.jsonSessionStart-hook RCE in the cloned PR working tree. This closes the sibling vector: a hostile.mcp.jsoncommitted in the same tree.Determination (verified, not assumed)
settingSources: []does not gate project.mcp.jsondiscovery:node_modules/@anthropic-ai/claude-agent-sdk/sdk.mjs) mapsstrictMcpConfig→ the CLI--strict-mcp-configflag,mcpServers→--mcp-config, andsettingSources→--setting-sources.--bareflag ("skip auto-discovery of hooks, skills, plugins, MCP servers, auto memory, and CLAUDE.md") shows MCP servers are auto-discovered by default and are a distinct item from settings/memory (whatsettingSourcescontrols).--strict-mcp-configrestricts MCP loading to the--mcp-configset, ignoring all other configuration including project.mcp.json.So with
cwd= the cloned PR tree +permissionMode: bypassPermissions, a hostile.mcp.jsonwas auto-discovered and loaded — registering a stdio MCP server whosecommandruns on connect, the same RCE primitive class as #191.Fix
src/core/executor.ts— addstrictMcpConfig: truetoqueryOptions, next to thesettingSources: []pin, with an inline comment recording the determination (the TS docstring only mentions validation, but the flag it emits also suppresses discovery).test/core/executor.test.ts— regression test:options.strictMcpConfig === true, the injectedmcpServersare still forwarded (no-loss), andsettingSourcesstays[].No-loss: the bot supplies all its MCP servers explicitly via
mcpServers; it never relies on a project.mcp.json, so this keeps every legitimate server and blocks only the attacker-controlled file.Acceptance criteria
.mcp.jsonatcwdIS auto-loaded independent ofsettingSources: [].strictMcpConfig: trueadded with a regression test; injectedmcpServerspreserved.Out of scope (residual, operator-controlled, not cloned-tree)
~/.claude.json, plugin-provided, and MCPB-bundled MCP servers live in operator-controlled locations, not the attacker-controllable PR tree. Both cloned-tree attacker config classes (settings.json,.mcp.json) are now closed.🤖 Generated with Claude Code
Summary by CodeRabbit