# The Patch Landed 24 August. OpenCode's Advisory Waited a Month.

> On 24 September 2026 Anomaly published GHSA-632h-h47v-g4x4 for OpenCode. A cross-site request to the local upgrade endpoint could make npm, pnpm, or Bun install an attacker-chosen package. The fix, release 1.18.22, shipped on 24 August. Anomaly did not request a CVE. Datadog says vulnerable versions were still a large share of downloads in the week before publication.

Source: https://hackerlogs.com/blog/opencode-upgrade-no-cve
Published: 2026-09-25

## Key takeaways

- Anomaly's GHSA-632h-h47v-g4x4 is the vendor primary. Datadog Security Labs is the researcher primary. Both are dated 24 September 2026.
- The cross-site path is the local HTTP server. npm, pnpm, and Bun installs passed the upgrade target to the package manager as a package spec.
- Release 1.18.22 shipped on 24 August. The advisory waited until 24 September because Anomaly asked for a month. There is no CVE.
- Datadog counts more than 647,000 downloads of 82 vulnerable versions from 17 to 23 September, 38.9% of OpenCode downloads that week.
- Curl, Homebrew, Chocolatey, and Scoop are outside this package-specifier path. A cached server password still rides on a top-level page load.

On 24 September Anomaly published [GHSA-632h-h47v-g4x4](https://github.com/anomalyco/opencode/security/advisories/GHSA-632h-h47v-g4x4). [Datadog Security Labs](https://securitylabs.datadoghq.com/articles/opencode-upgrade-remote-code-execution/) published the research the same day. The fix had already shipped. OpenCode 1.18.22, which restricts the upgrade target to a semantic version and rejects the loose content type, was released on 24 August. Anomaly asked Datadog to wait a month. Anomaly did not request a CVE.

Hacker News on 25 September led with an Ollama-style model tool and a new reconstruction of the Hugging Face incident, which this archive already covers. US X trends were television, golf, and football. Google News over the last two days carried the Agentforce disclosure and the OpenAI review, not this GHSA.

 The advisory rates it High. The local server can ask npm, pnpm, or Bun to install a package the request names. High because that install runs as the user who started the server, not because a CVE number exists.

<img src="/opencode-upgrade-no-cve.svg" alt="Three panels for the OpenCode upgrade advisory: a local server that accepted a package target, a fix that shipped on 24 August with no CVE, and downloads of old builds that continued into the week before publication." width="1200" height="675" />

## What the advisory actually bounds.

OpenCode is Anomaly's coding agent. `opencode serve` starts an HTTP server, on port 4096 in the examples both primaries use. Datadog shows `opencode web` starting that same server and printing a warning when `OPENCODE_SERVER_PASSWORD` is unset. The upgrade route accepts a target and, for an npm, pnpm, or Bun install, hands that string to the package manager as the thing to install. A semantic version was the intended input. A package spec can also be a remote archive. The route did not require a JSON content type, so a cross-site page load could submit a body the server still parsed. The advisory names that pair: origin was not checked, and the target was not limited to a version.

The advisory's affected range is 1.14.30 and later. The resolution names 1.18.22 as the patched release, in PR 44686, commit c6e76e9. That change requires an explicit target, requires it to be a semantic version, requires the supported JSON content type, and rejects a bodyless upgrade. A sentence in the advisory body says the author believes the impacted set stops at 1.18.16, because that is when a raw handler began accepting a body that is not JSON. Datadog's range is 1.14.30 through 1.18.21 inclusive. Use 1.18.22 as the floor. Do not shop the three sentences for the one that leaves you on an old build.

Curl, Homebrew, Chocolatey, and Scoop installs do not interpret the target as an alternate package. The advisory says the standalone CLI upgrade command is not itself the cross-site surface. Users who are not running the HTTP server are outside that path.

> The CVE field on GHSA-632h-h47v-g4x4 is empty because Anomaly chose not to request one. Datadog quotes the reason: Anomaly believes CVEs on GitHub Security Advisories reward volume. The advisory still rates the issue High, under origin validation, cross-site request forgery, and interpretation conflict. A program that waits for a CVE identifier will wait forever on this one.

A password is not a full stop. The advisory says basic authentication blocks an unauthenticated request, and that a browser which has already signed in will attach those cached credentials to a top-level navigation. Datadog makes the same point. The warning the server prints when the password is unset is accurate. Setting the password does not retire the route.

## The package clock and the impact clock.

The package clock is the release. Datadog's timeline puts the vulnerable path in PR 24853 on 29 April, and the first vulnerable release, 1.14.30, on 30 April. Datadog found it on 11 August and reported it the same day through the GitHub advisory. Anomaly opened, merged, and released the fix on 24 August as 1.18.22, and the same day asked for a one-month publication delay. The public post and the public GHSA are both 24 September. That is 31 days of a fixed package with no public identifier.

The impact clock is who was still running the old server. Datadog's npm count for 17 through 23 September, three weeks after 1.18.22, is more than 647,000 downloads across 82 vulnerable versions. That was 38.9% of OpenCode downloads in the window. The count is not unique users, and it is not a count of people who had `opencode serve` or `opencode web` listening. It is evidence that "patched on 24 August" did not drain the old builds before the advisory existed.

> Upgrading today closes the next page load. It does not close a user account that already installed a package the server was told to fetch. If a pre-1.18.22 npm, pnpm, or Bun install had the HTTP server up while a browser on that machine loaded untrusted pages, treat that account's tokens as exposed. The download percentage is not that finding. The condition in the advisory is.

This is the same split as the [TanStack token](/blog/tanstack-token-lasted-months) and the [MemTensor tag](/blog/memtensor-sckit-latest-tag). The registry can grow a fixed version in a day. Laptops and CI images keep the version they resolved. Here the fixed version existed for a month before the identifier operators search for was published, and the identifier is a GHSA, not a CVE.

## What this is not.

It is not [GHSA-vxw4-wv6m-9hhh](https://github.com/anomalyco/opencode/security/advisories/GHSA-vxw4-wv6m-9hhh), the January advisory for an unauthenticated server that could run commands, tracked as CVE-2026-22812. Different report, different code path, and that one did get a CVE. Mixing them will send a patch program at the wrong release.

It is not a claim that every OpenCode user was reachable. No server, no cross-site path. A curl or Homebrew install does not take the arbitrary-package branch the advisory describes. An npm install that never ran the server is a version to upgrade, not an account to declare burned.

It is not an in-the-wild campaign. Neither primary reports exploitation outside the lab. Do not invent victim counts from the 647,000 figure. That figure is downloads.

It is also not a bug you can hand to a CVE-only gate. The ticket name is the GHSA, the version floor 1.18.22, and the install method.

## What to do.

1. Find every host running `opencode serve` or `opencode web`. Upgrade those installs to 1.18.22 or later. Check the binary on the host, not the version a different machine resolved last week.
2. If the install method is npm, pnpm, or Bun and the version was below 1.18.22, and the server was listening while a browser on that host loaded pages you do not trust, rotate the tokens in that user account. The advisory's impact is code execution as that user. Include CI jobs that start the server for a test.
3. Keep the server on localhost, and set a password anyway. Then assume a browser that has already authenticated will resend those credentials on a top-level navigation. The password is a speed bump in that case, which is what both primaries say. Do not publish port 4096.
4. Record the install method next to the version. Curl, Homebrew, Chocolatey, and Scoop are outside the package-specifier path. They are not a reason to skip 1.18.22 if an npm install of the same tool also exists on the fleet.
5. Alert on GitHub advisories for `opencode-ai`, not only on a CVE feed. This GHSA has no CVE. A gate that requires one will stay green while the server is still old.
6. Treat an agent upgrade route as a supply-chain control. A local server that can install a global package from a string in a request is the same class of bug as a plugin installer that trusts a pin it never checks. The [Plugin4Shell](/blog/plugin4shell-sha-pin-rce) brief was the pin. This one is the upgrade target.

The front page did not need this for the fact to be operational. For 31 days the fixed release existed, the old builds were still what a large share of downloads resolved, and the public record had no CVE to search.

## Sources

- [Discovering and exploiting a remote code execution vulnerability in OpenCode (GHSA-632h-h47v-g4x4)](https://securitylabs.datadoghq.com/articles/opencode-upgrade-remote-code-execution/) (2026-09-24)
- [Cross-site OpenCode server upgrade request can install arbitrary packages for npm-based installations](https://github.com/anomalyco/opencode/security/advisories/GHSA-632h-h47v-g4x4) (2026-09-24)
