Skip to content
Betav0.62.0
All articles

An MCP login link that ran code: opencode's fix shipped without an advisory

A remote MCP server could run commands on Windows and WSL machines through opencode's OAuth flow. The fix is out, but no CVE or advisory will flag it.

By The SpanDock team

5 min read

A diagram: a remote MCP server's discovery document supplies a sign-in URL, the coding agent hands it to a browser launcher, and on Windows the launcher builds a PowerShell command that evaluates text inside the URL; on macOS and Linux the launcher passes it as a plain argument

Connecting a coding agent to a remote MCP server can be enough to run code on the developer's machine. Pillar Security has published details of a flaw in opencode, the open-source AI coding agent, where a server-supplied OAuth login address reached a PowerShell command on Windows and in WSL. The fix shipped in opencode 1.18.33 on 28 September 2026. There is no CVE and no security advisory, so the usual scanners and dependency alerts won't tell you whether you are affected.

What happened

Remote MCP servers that need a login use OAuth discovery. The server answers an unauthenticated request with 401 and a pointer to its metadata, and that metadata tells the client where to send the user to sign in. One of those fields, authorization_endpoint, is a free-form string chosen by the server.

According to Pillar Security's write-up, opencode passed that string to the popular open package to launch a browser, without checking it against the server the user had configured. On macOS and Linux, open starts the browser with an argument list, so no shell is involved. On Windows, the version opencode used, open@10.1.2, built a PowerShell command and did not escape the target. PowerShell evaluates $(...) inside double-quoted strings, so a URL containing such an expression ran it before the browser launch failed. Pillar's example payload is an ordinary https:// address.

Pillar lists the affected range as opencode 1.0.137 to 1.18.32 on Windows and WSL. It proposes a CVSS 3.1 score of 9.8, which would be critical, but that is the researcher's proposal: no official record or score exists. The write-up also points out that the server did not need to be malicious when someone added it. The payload arrives in a response at connection time, so a server that is compromised later, or a domain that expires and is re-registered, would do.

How it was fixed, and why nobody will be told

The fix is pull request 51414, merged on 25 September. It is titled as a refactor: it consolidates eight places that launched a browser behind one openUrl() function, which accepts only http: and https: URLs. It adds the same scheme check where the MCP OAuth provider forwards a sign-in URL, and it moves open from 10.1.2 to 11.0.4. The 1.18.33 release notes mention only that "MCP browser launch failures are now reported when the launcher exits immediately." Neither the pull request nor the release mentions security.

Pillar says opencode's maintainers treated a malicious MCP server as outside their threat model, and did not request a CVE. That is a reasonable position for a project to hold about its own scope, and the fix itself is thorough. It still leaves defenders with a problem: a vulnerability that is public in the diff and invisible in every feed they monitor.

There is also a small inconsistency in the source. The published page is dated 19 October 2026, while its own disclosure timeline says the report was first published on 4 October. Either way, the fix has been available for about three weeks.

Scheme checks are not the fix

The most useful part of the research is its argument about what actually closed the hole. The new scheme check would not have stopped the payload, because the payload is a valid https: URL. What stopped it was the dependency upgrade: open 11 quotes the target so that PowerShell no longer expands it. Pillar says the package fixed its escaping in 11.0.0, released in November 2025, and that opencode added the vulnerable call in December 2025 while still pinned to an older 10.x release.

This class of bug is not new. CVE-2025-6514, published in July 2025, was an OS command injection in mcp-remote through untrusted MCP server connections, rated 9.6 (critical) and fixed in 0.1.16. Pillar names two more 2025 CVEs with the same pattern. The common lesson people took from them was to validate URL schemes. Pillar reports that the MCP TypeScript SDK still blocks only javascript:, data: and vbscript: by default, which would also let this payload through.

The more durable rule is simpler: never build a shell command from a string a remote party supplied. Pass it as an argument, which Pillar says several other MCP clients already do. And bind OAuth discovery to the origin the user actually configured: Pillar points to github-mcp-server, which takes authorisation servers from the operator instead of discovering them from the server it connects to. We covered the server-side mirror of this problem in MCP servers trusting the wrong URLs, and a related client flaw in the TypeScript SDK's OAuth issuer handling.

What it means for engineering and security leaders

  • An MCP client is a parser of untrusted input. Discovery documents, server metadata, error strings and tool descriptions all come from a third party. Prompt injection gets most of the attention, but this flaw never involved the model at all.
  • CVE-driven patching misses agent fixes. This is the second pattern this month where the record lagged or never appeared. In three Claude advisories, the fixes shipped months before the advisories. Here the record will probably never exist. For AI coding tools, track versions directly.
  • Threat models differ between vendor and customer. A project may reasonably say a hostile MCP server is out of scope. A company that lets developers add remote servers cannot. Ask vendors how their client treats server-controlled fields, and write the answer down.
  • Windows needs its own testing. The same code was safe on two platforms and exploitable on the third, because one dependency behaved differently there.

Practical takeaways

  • Upgrade opencode to 1.18.33 or later on every Windows and WSL machine.
  • Find installations yourself. No scanner will match this, so check package manifests, global npm installs and developer images for opencode-ai versions in the affected range.
  • Until a machine is upgraded, remove remote MCP servers from its opencode configuration that nobody has vetted.
  • If you maintain internal tools that open URLs, check which version of open (or any launcher) they use, and pass URLs as arguments rather than through a shell.
  • Add a review step for remote MCP servers: who runs them, which domain they live on, and who would notice if that domain changed hands.

Knowing where a tool runs is the first step when there is no CVE to search for. SpanDock's process inventory lists the AI tools and helper processes running on each computer, including tools that send no telemetry, with each program's name and path. The docs don't say it records versions, so use it to find the machines, then check the version on each. Process inventory is on the Enterprise plan.

Sources

  1. Pillar Security: Open and Shut, remote code execution in opencode via MCP OAuth
  2. anomalyco/opencode release v1.18.33
  3. anomalyco/opencode pull request 51414: refactor(core): share a browser opener across opencode and tui
  4. GitHub advisory GHSA-6xpm-ggf7-wc3p (CVE-2025-6514): mcp-remote OS command injection via untrusted MCP server connections
Cookie categories

Details: Cookie Policy.