Have a project in mind? Let's talk.

MCP OAuth security is now a developer-machine problem, not only a server problem. On October 19, Pillar Security published research showing that an attacker-controlled remote Model Context Protocol server could use the OAuth discovery flow to run code on Windows and Windows Subsystem for Linux machines through opencode. Source
The flaw matters because coding agents can already read files, run commands, and use external systems with the developer's privileges. The attack did not need prompt injection, a malicious package install, or an AI model mistake. It used a server-controlled OAuth field and a browser-opening path that passed an untrusted URL into PowerShell. Source
This checklist explains what happened, which controls the MCP specification already expects, and what teams should check in their own agents and MCP clients.
Pillar says opencode versions 1.0.137 through 1.18.32 were affected on Windows and WSL when remote MCP servers were configured. Version 1.18.33, released September 28, 2026, contains the fix. Pillar proposed a 9.8 Critical CVSS score, but says no public CVE was published. Source
The vulnerable flow started when a remote MCP server returned a 401 challenge and discovery documents. One field, authorization_endpoint, told the client where to send the user for login. In affected opencode versions, that server-controlled value traveled through the MCP SDK and opencode's browser-opening code into the open package and then PowerShell. Source
The Windows version of the open package built a powershell -EncodedCommand command. The application name was escaped, but the target URL was not. PowerShell expands $(...) inside double-quoted strings, so a normal-looking HTTPS URL could execute a subexpression before the browser launch failed. Source
Pillar's central lesson is direct: a remote MCP server is an untrusted peer, and the MCP client is a parser of untrusted input. Discovery documents, server metadata, tool descriptions, resource descriptors, and error strings all arrive before the model reasons about them. Source
A common response to URL execution bugs is to allow only http: and https:. Pillar says that would not have stopped this payload because the payload used an ordinary HTTPS URL. The durable fix is to pass the URL as an argument vector and never build a shell command from a remote string. Source
Pillar reviewed other MCP clients and found stronger patterns. Some use a scheme-gated execFile opener, some prevent the OAuth path from passing server-controlled values to the opener, and some validate OAuth endpoints behind an HTTPS allowlist with an argument-vector opener. The common control is not the scheme check. It is the absence of a shell. Source
That does not make scheme validation useless. The MCP security guide says clients must only allow HTTP and HTTPS for authorization URLs, restrict HTTP to loopback development, reject dangerous schemes such as javascript:, data:, file:, and vbscript:, and prefer allowlists over blocklists. Source
Use both controls. Validate the scheme, then open the validated URL without a shell. If either control is missing, the OAuth flow remains a risky path from a remote server to local execution.
The MCP authorization specification defines OAuth for HTTP-based transports. Authorization is optional, but HTTP implementations that support it should follow the specification. STDIO implementations should not use this flow and should retrieve credentials from the environment instead. Source
In the specification, the MCP server acts as an OAuth 2.1 resource server, the MCP client acts as an OAuth 2.1 client, and the authorization server interacts with the user and issues access tokens. The authorization server may be hosted with the resource server or run separately. Source
MCP servers advertise their authorization servers through Protected Resource Metadata, while clients use authorization server metadata to discover endpoints and capabilities. Clients must obtain a client ID through Client ID Metadata Documents, pre-registration, or Dynamic Client Registration. Source
For least privilege, MCP servers should include a scope parameter in the WWW-Authenticate header for the current operation. Clients must treat challenged scopes as authoritative for that operation and should include them alongside existing scopes when re-authorizing, so a new request does not silently remove permissions. Source
The specification also requires a resource parameter in authorization and token requests. The value identifies the MCP server that will receive the token, using the server's canonical URI. Access tokens belong in the Authorization header and must not appear in a URI query string. Source
MCP security is not only the client-side opener. The MCP security guide describes a confused deputy attack where a proxy MCP server uses a static client ID with a third-party authorization server. Without per-client consent, a malicious client can combine dynamic registration, a crafted redirect URI, and a consent cookie to obtain an authorization code without the user's explicit approval. Source
To prevent that attack, the guide says proxy servers must maintain per-user, per-client consent before starting the third-party authorization flow. The consent page must identify the MCP client, show the requested third-party scopes, show the registered redirect URI, use CSRF protection, and prevent iframing. Source
Redirect URI checks need exact matching. The guide says proxy servers must validate that the requested redirect_uri exactly matches the registered URI, reject changed values, and avoid pattern matching or wildcards. Source
The OAuth state parameter needs the same care. Generate a cryptographically secure value for each request, store it server-side or in an encrypted cookie only after consent, set tracking immediately before the identity-provider redirect, and reject callbacks with missing or mismatched state. Source
OAuth discovery makes clients fetch server-provided URLs. The MCP security guide warns that this can create server-side request forgery when the client runs on a server. Examples include cloud metadata endpoints, localhost services, DNS rebinding, and redirect chains into internal resources. Source
The guide says production clients should require HTTPS for OAuth-related URLs, with an explicit development opt-out for loopback addresses. It also says clients should block private and reserved IP ranges. Apply the same policy to authorization metadata, token endpoints, registration endpoints, logo URLs, and any other server-supplied URL the client fetches. Source
For company networks, add egress rules. A desktop agent should not be able to reach cloud metadata services. A server-side agent should resolve and fetch discovery URLs through a controlled egress path. Log the final IP, redirect chain, TLS failure, and blocked destination.
Inventory every MCP client, server, proxy, and remote server URL. Record owner, environment, transport, scopes, and the data or actions available.
For opencode, find Windows and WSL installations running versions 1.0.137 through 1.18.32 with remote MCP servers. Upgrade to 1.18.33 or later, or remove unvetted remote servers until the upgrade lands. Source
Search code for shell, cmd, PowerShell, EncodedCommand, string-built open commands, and browser launch helpers that receive remote values. Replace them with argument-vector process calls.
Bind OAuth discovery to the configured MCP server origin. Treat a server that names a different authorization endpoint as a policy decision that needs review, not a harmless convenience.
Enforce HTTPS in production. Allow HTTP only for localhost development, and make that exception visible in configuration.
Validate every authorization URL with an allowlist. Then open it through a non-shell, platform-specific mechanism. Never pass the remote URL through cmd, sh, or PowerShell.
Use the resource parameter with the canonical MCP server URI. Reject tokens sent in URLs and send bearer tokens only in the Authorization header.
For proxies, require per-user and per-client consent. Show the client name, scopes, and exact redirect URI before continuing to the third-party provider.
Validate state and redirect_uri exactly. Reject missing, changed, wildcard, or mismatched values.
Log the OAuth path as part of agent observability. Capture the client, server, authorization server, scopes, resource URI, redirect outcome, policy denial, and token refresh. Our AI agent observability checklist covers the wider telemetry baseline.
Add security tests for the fields your client parses. Use a test MCP server that returns discovery documents with unusual schemes, PowerShell subexpression strings, redirect chains, private IP targets, very long fields, Unicode hostnames, and missing metadata. The client should reject or safely display the value without executing it.
Test every supported operating system. Pillar notes that macOS and Linux used non-shell launchers in this case, while Windows took the vulnerable path. A cross-platform agent needs per-platform tests for browser opening, file paths, environment variables, and process creation. Source
Finally, test the failure path. A failed browser launch should not hide a command-injection attempt. A denied authorization endpoint should produce a clear security event. A token refresh failure should not cause the client to retry with broader scopes.
The opencode issue is a useful warning because it sits before model reasoning. A remote MCP server supplied OAuth metadata, the client trusted a URL field, and the platform opener turned that field into a command-line risk.
MCP OAuth security needs the boring controls done well: trusted server inventory, exact origin binding, HTTPS, scoped tokens, canonical resource URIs, per-client consent, exact redirect and state checks, SSRF defenses, complete logs, and no shell around remote input. If your MCP client cannot show those controls, fix the client before connecting another server.
MCP OAuth security is the set of controls around OAuth discovery, client registration, scopes, redirect URIs, state, tokens, and consent in Model Context Protocol clients and servers. It covers both server access and client-side handling of server-provided URLs.
Pillar Security says opencode versions 1.0.137 through 1.18.32 were affected on Windows and WSL when remote MCP servers were configured. Version 1.18.33 contains the fix.
No. HTTPS validation blocks some unsafe schemes, but Pillar's payload used a normal HTTPS URL. Clients should validate URLs and also open them with an argument-vector, non-shell mechanism.
The MCP authorization specification says STDIO implementations should not follow the HTTP authorization flow. They should retrieve credentials from the environment instead.
Inventory MCP clients and remote servers, upgrade affected opencode installations, remove unvetted remote servers, and check whether any client passes server-controlled URLs into shell commands.
Ready to take the first step towards unlocking opportunities, realizing goals, and embracing innovation? We're here and eager to connect.