fix(core): prevent SSRF in MCP OAuth metadata discovery and authentication - #29081
fix(core): prevent SSRF in MCP OAuth metadata discovery and authentication#29081josebalius wants to merge 2 commits into
Conversation
…ation Enforce RFC 9728 Section 7.7 and RFC 8414 security constraints during MCP OAuth discovery, dynamic client registration, and token exchange/refresh. - Enforce HTTPS for remote OAuth endpoints (allow HTTP only for loopback when connecting to local MCP servers) - Validate origin matching for resource_metadata in WWW-Authenticate challenges - Block private IPv4/IPv6 address ranges, loopback endpoints from remote servers, link-local / IMDS (169.254.169.254), benchmark ranges (198.18.0.0/15), and multicast/broadcast - Perform asynchronous DNS resolution to prevent DNS rebinding attacks against internal IP ranges - Validate dynamic client registration endpoints and token exchange/refresh URLs prior to issuing requests - Add comprehensive test coverage in oauth-utils.test.ts, oauth-provider.test.ts, and oauth-flow.test.ts
|
📊 PR Size: size/L
|
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly hardens the security of the Model Context Protocol (MCP) OAuth implementation by introducing robust defenses against Server-Side Request Forgery (SSRF). By enforcing strict validation on all OAuth-related endpoints and implementing DNS rebinding protections, the changes ensure that remote MCP servers cannot force the client to interact with sensitive internal network resources or cloud metadata services. Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. Footnotes
|
|
Size Change: +6.56 kB (+0.02%) Total Size: 35.3 MB
ℹ️ View Unchanged
|
There was a problem hiding this comment.
Code Review
This pull request introduces SSRF protections and URL security validations for OAuth endpoints per RFC 9728 Section 7.7, including DNS resolution checks to block private IP addresses. Feedback focuses on critical security issues where remote MCP servers could bypass loopback restrictions due to incorrect allowLoopback evaluation logic during client registration, metadata discovery, and token exchange. Additionally, the reviewer noted that asynchronous DNS lookups alone do not fully prevent DNS rebinding attacks and suggested pinning resolved IPs or using a custom agent.
Note: Security Review did not run due to the size of the PR.
… registration and discovery
Enforce RFC 9728 Section 7.7 and RFC 8414 security constraints during MCP OAuth discovery, dynamic client registration, and token exchange/refresh.
Summary
Prevents Server-Side Request Forgery (SSRF) during Model Context Protocol (MCP) OAuth 2.0 metadata discovery, dynamic client registration, and token exchange/refresh flows by implementing strict URL validation, origin matching, and network boundary enforcement per RFC 9728 Section 7.7 and RFC 8414.
Details
Remote MCP servers returning unvalidated
WWW-Authenticate: Bearer resource_metadata="..."challenge headers orauthorization_serversURLs could previously trigger out-of-band HTTP requests to internal IP addresses, local services (localhost/127.0.0.1), or cloud instance metadata services (IMDS at169.254.169.254).Core Protections Implemented:
https:for all remote endpoints.http:only for loopback addresses (localhost,127.0.0.1,[::1]) when explicitly connecting to a local MCP server (allowLoopback: true).allowLoopback: false).resource_metadatainWWW-Authenticatestrictly matches the MCP server's origin.10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,100.64.0.0/10), link-local / IMDS (169.254.169.254), benchmark testing (198.18.0.0/15), IPv6 private/link-local ranges, and multicast/broadcast addresses.node:dns/promisesand validates all resolved IP addresses against private network boundaries before issuing HTTP requests.MCPOAuthProvider.registerClient()before issuing registration POST requests.tokenUrlinexchangeCodeForToken()andrefreshAccessToken()before issuing token requests.OAuthSecurityErrorwithout swallowing security rejections.How to Validate
1. Automated Tests
Run the targeted OAuth unit tests covering SSRF attack scenarios, cloud metadata blocking, DNS rebinding, and origin matching:
npm test -w @google/gemini-cli-core -- src/mcp/oauth-utils.test.ts src/mcp/oauth-provider.test.ts src/utils/oauth-flow.test.tsRun full typecheck and linting:
2. Edge Cases Verified:
authorization_servers: ["http://127.0.0.1:18080"]-> ThrowsOAuthSecurityError.resource_metadata="http://169.254.169.254/computeMetadata/v1"-> ThrowsOAuthSecurityError.127.0.0.1or169.254.169.254(DNS rebinding) -> ThrowsOAuthSecurityError.WWW-Authenticateheader with unquotedresource_metadata=https://example.com/oauth/metadatavs quoted strings -> Both parsed and validated.http://localhost:3000-> Loopback permitted, non-loopback private IPs still blocked.Pre-Merge Checklist