ghsa-33f5-2c5q-wgwj
CVSS 8.2 osv_rustsec### Summary The `rmcp` library does not validate the `resource` parameter in OAuth Protected Resource metadata (RFC 9728), allowing a malicious MCP server to redirect OAuth flows to a legitimate authorization server and steal the resulting access tokens. ### Details RFC 9728 specifies two MUST requirements for resource parameter validation: - Section 7.3: the client MUST ensure that the resource identifier URL it is using as the prefix for the metadata request exactly matches the `resource` value in the returned metadata document. - Section 3.3: if the `resource` value returned is not identical to the URL the client used, the data MUST NOT be used. In the current implementation (`crates/rmcp/src/transport/auth.rs`), the `ResourceServerMetadata` struct (lines 390–394) does not include a resource field: ```rust struct ResourceServerMetadata { authorization_server: Option<String>, authorization_servers: Option<Vec<String>>, scopes_supported: Option<Vec<String>>, } ``` And discover_oauth_server_via_resource_metadata() (lines 1446–1465) proceeds without any resource URL validation. #### Recommended fix 1. Add the `resource` field to the struct: ```rust struct ResourceServerMetadata { resource: Option<String>, // RFC 9728 REQUIRED field authorization_server: Option<String>, authorization_servers: Option<Vec<String>>, scopes_supported: Option<Vec<String>>, } ``` 2. Add validation logic after fetching metadata: ```rust let Some(resource_metadata) = self .fetch_resource_metadata_from_url(&resource_metadata_url) .await? else { return Ok(None); }; // RFC 9728: validate that the resource identifier matches our target server if let Some(resource) = &resource_metadata.resource { if resource.trim_end_matches('/') != self.base_url.as_str().trim_end_matches('/') { return Err(AuthError::MetadataError(format!( "Resource metadata mismatch: expected '{}', got '{}'", self.base_url, resource ))); } } ``` ### PoC 1. Attacker sets up a malicious MCP server at `fake-mcp.com/mcp`. 2. At `fake-mcp.com/mcp/.well-known/oauth-protected-resource`, the attacker serves metadata declaring: - resource: `real-mcp.com/mcp` (the legitimate server) - authorization_servers: the legitimate authorization server(s) of `real-mcp.com/mcp` 3. Victim configures any MCP client using `rmcp` to connect to `fake-mcp.com/mcp`. 4. `rmcp` fetches the protected resource metadata and, without validating that the `resource` field (`real-mcp.com/mcp`) differs from the configured server (`fake-mcp.com/mcp`), initiates an OAuth flow with the legitimate authorization server. 5. The victim sees a legitimate authorization prompt and completes the flow. 6. The resulting access token — valid for `real-mcp.com/mcp` — is sent to `fake-mcp.com/mcp` in subsequent requests. 7. The attacker captures the token and can impersonate the victim on `real-mcp.com/mcp`. ### Impact This is an access token theft vulnerability via OAuth resource metadata spoofing. All MCP clients built on `rmcp` that rely on OAuth-protected MCP servers are affected. An attacker who tricks a user into connecting to a malicious MCP server can steal valid access tokens for any legitimate MCP server, enabling full impersonation of the victim. #### Credit Jian Cui, Minsun Shim, Zhou Li, Xiaojing Liao University of Illinois Urbana-Champaign (UIUC) University of California, Irvine (UCI)
- Published
- unknown
- Last Modified
- unknown
CVSS details not available.
No product information available.
- https://github.com/modelcontextprotocol/rust-sdk/security/advisories/GHSA-33f5-2c5q-wgwj
- https://nvd.nist.gov/vuln/detail/CVE-2026-63127
- https://github.com/modelcontextprotocol/rust-sdk/pull/937
- https://github.com/modelcontextprotocol/rust-sdk/commit/c1a8b29ff2cc45e7820b900dae42cbb4958089ec
- https://github.com/modelcontextprotocol/rust-sdk
- https://github.com/modelcontextprotocol/rust-sdk/releases/tag/rmcp-v2.0.0
No linked vulnerabilities found.
{
"affected": [
{
"database_specific": {
"source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/09/GHSA-33f5-2c5q-wgwj/GHSA-33f5-2c5q-wgwj.json"
},
"package": {
"ecosystem": "crates.io",
"name": "rmcp",
"purl": "pkg:cargo/rmcp"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "2.0.0"
}
],
"type": "SEMVER"
}
]
}
],
"aliases": [
"CVE-2026-63127"
],
"database_specific": {
"cwe_ids": [
"CWE-345"
],
"github_reviewed": true,
"github_reviewed_at": "2026-09-16T22:13:26Z",
"nvd_published_at": "2026-09-16T15:17:39Z",
"severity": "HIGH"
},
"details": "### Summary\nThe `rmcp` library does not validate the `resource` parameter in OAuth Protected Resource metadata (RFC 9728), allowing a malicious MCP server to redirect OAuth flows to a legitimate authorization server and steal the resulting access tokens.\n\n### Details\nRFC 9728 specifies two MUST requirements for resource parameter validation:\n- Section 7.3: the client MUST ensure that the resource identifier URL it is using as the prefix for the metadata request exactly matches the `resource` value in the returned metadata document.\n- Section 3.3: if the `resource` value returned is not identical to the URL the client used, the data MUST NOT be used.\n\nIn the current implementation (`crates/rmcp/src/transport/auth.rs`), the `ResourceServerMetadata` struct (lines 390–394) does not include a resource field:\n```rust\nstruct ResourceServerMetadata {\n authorization_server: Option<String>,\n authorization_servers: Option<Vec<String>>,\n scopes_supported: Option<Vec<String>>,\n}\n```\nAnd discover_oauth_server_via_resource_metadata() (lines 1446–1465) proceeds without any resource URL validation.\n\n#### Recommended fix\n1. Add the `resource` field to the struct:\n ```rust\n struct ResourceServerMetadata {\n resource: Option<String>, // RFC 9728 REQUIRED field\n authorization_server: Option<String>,\n authorization_servers: Option<Vec<String>>,\n scopes_supported: Option<Vec<String>>,\n }\n ```\n2. Add validation logic after fetching metadata:\n ```rust\n let Some(resource_metadata) = self\n .fetch_resource_metadata_from_url(&resource_metadata_url)\n .await?\n else {\n return Ok(None);\n };\n \n // RFC 9728: validate that the resource identifier matches our target server\n if let Some(resource) = &resource_metadata.resource {\n if resource.trim_end_matches('/') != self.base_url.as_str().trim_end_matches('/') {\n return Err(AuthError::MetadataError(format!(\n \"Resource metadata mismatch: expected '{}', got '{}'\",\n self.base_url, resource\n )));\n }\n }\n ```\n\n### PoC\n\n1. Attacker sets up a malicious MCP server at `fake-mcp.com/mcp`. \n2. At `fake-mcp.com/mcp/.well-known/oauth-protected-resource`, the attacker serves metadata declaring:\n - resource: `real-mcp.com/mcp` (the legitimate server)\n - authorization_servers: the legitimate authorization server(s) of `real-mcp.com/mcp`\n\n\n3. Victim configures any MCP client using `rmcp` to connect to `fake-mcp.com/mcp`.\n\n4. `rmcp` fetches the protected resource metadata and, without validating that the `resource` field (`real-mcp.com/mcp`) differs from the configured server (`fake-mcp.com/mcp`), initiates an OAuth flow with the legitimate authorization server.\n5. The victim sees a legitimate authorization prompt and completes the flow.\n6. The resulting access token — valid for `real-mcp.com/mcp` — is sent to `fake-mcp.com/mcp` in subsequent requests.\n7. The attacker captures the token and can impersonate the victim on `real-mcp.com/mcp`.\n\n### Impact\nThis is an access token theft vulnerability via OAuth resource metadata spoofing. All MCP clients built on `rmcp` that rely on OAuth-protected MCP servers are affected. An attacker who tricks a user into connecting to a malicious MCP server can steal valid access tokens for any legitimate MCP server, enabling full impersonation of the victim.\n\n#### Credit\nJian Cui, Minsun Shim, Zhou Li, Xiaojing Liao\nUniversity of Illinois Urbana-Champaign (UIUC)\nUniversity of California, Irvine (UCI)",
"id": "GHSA-33f5-2c5q-wgwj",
"modified": "2026-09-16T22:30:08.107391372Z",
"published": "2026-09-16T22:13:26Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/modelcontextprotocol/rust-sdk/security/advisories/GHSA-33f5-2c5q-wgwj"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-63127"
},
{
"type": "WEB",
"url": "https://github.com/modelcontextprotocol/rust-sdk/pull/937"
},
{
"type": "WEB",
"url": "https://github.com/modelcontextprotocol/rust-sdk/commit/c1a8b29ff2cc45e7820b900dae42cbb4958089ec"
},
{
"type": "PACKAGE",
"url": "https://github.com/modelcontextprotocol/rust-sdk"
},
{
"type": "WEB",
"url": "https://github.com/modelcontextprotocol/rust-sdk/releases/tag/rmcp-v2.0.0"
}
],
"schema_version": "1.9.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:L/A:N",
"type": "CVSS_V3"
}
],
"summary": "RMCP: Missing Resource Field Validation in OAuth Protected Resource Metadata Discovery"
}