Skip to navigation

Threat reportVulnerabilityTL-2026-5809

OpenCode Remote Code Execution via /global/upgrade Content-Type Confusion and Cross-Site Request (GHSA-632h-h47v-g4x4)

highPATCHED

The /global/upgrade endpoint of the OpenCode AI coding agent's local HTTP server parses text/plain bodies as JSON, does not validate Origin, and passes an attacker-chosen package specifier to npm/pnpm/Bun. A malicious webpage can submit a cross-origin form to the local server and make it install an attacker-controlled package whose lifecycle script runs code. First disclosed .

Key facts

IdentifiersTL-2026-5809
Also known asGHSA-632h-h47v-g4x4, WS-2026-0073
SeverityHIGH
CVSS7.5 (CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H)
First disclosed
Affected productsAnomaly (anomalyco) OpenCode (npm: opencode-ai), npm/pnpm/Bun installations
Weaknesses (CWE)CWE-346, CWE-352, CWE-436
Malwareglobal
ToolsOpenCode
MITRE ATT&CK techniquesT1059 Command and Scripting Interpreter, T1190 Exploit Public-Facing Application, T1195.002 Supply Chain Compromise: Compromise Software Supply Chain, T1203 Exploitation for Client Execution, T1608.001 Stage Capabilities: Upload Malware
MotivationUNKNOWN
Target sectorstechnology, software-development
Target regionsGlobal
Detection rules9 (1 shown free)
Sources6 cited sources

Detection coverage

As of 2026-11-12, Threadlinqs Intelligence publishes 9 detection rule(s) for TL-2026-5809 across Splunk SPL, Microsoft KQL and Sigma, covering 6 indicator(s) of compromise. The whole corpus is readable without an account. Every threat comes with one complete detection in Splunk SPL, Microsoft KQL and Sigma, free for everyone; a free account adds daily TL Creds to unlock the rest. Paid plans add a larger daily allowance, correlation and the MCP server. Threadlinqs MCP server · View plans.

Free detection: OpenCode Server Spawns Global Package Install From Remote Tarball — Exploitation (GHSA-632h-h47v-g4x4)

Detects the OpenCode process (opencode serve / opencode web) launching npm, pnpm or Bun with a global install whose package specifier is a remote tarball or URL. This is the post-request behaviour of GHSA-632h-h47v-g4x4: a cross-origin text/plain POST to /global/upgrade passes an attacker-chosen 'target' to the package manager, whose preinstall script then runs code. Behaviour-first: it does not depend on the unlogged HTTP request.

  • Languages: Splunk SPL, Microsoft KQL, Sigma
  • ATT&CK: T1190, T1195.002, T1203
  • Data sources: sysmon, windows_process_creation
  • Severity: high
  • Confidence: high

Splunk SPL

index=sysmon sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=1 earliest=-24h (ParentImage="*opencode*" OR ParentCommandLine="*opencode*") (Image="*npm*" OR Image="*pnpm*" OR Image="*bun.exe" OR Image="*node.exe") (CommandLine="* -g*" OR CommandLine="* --global*" OR CommandLine="* global add*") (CommandLine="*http://*" OR CommandLine="*https://*" OR CommandLine="*.tgz*" OR CommandLine="*git+*" OR CommandLine="*file:*")
| rex field=CommandLine "(?i)(?<target_spec>(?:https?|git[+]\w+|file):[^\s'\x22]+|[^\s'\x22]+[.]tgz)"
```comment: OpenCode (opencode serve/web) spawning a global npm/pnpm/bun install with a remote tarball/URL specifier is the GHSA-632h-h47v-g4x4 exploit chain```
| table _time host user ParentImage ParentCommandLine Image CommandLine target_spec

Microsoft KQL

DeviceProcessEvents
| where Timestamp > ago(24h)
| where InitiatingProcessFileName has "opencode" or InitiatingProcessCommandLine has "opencode"
| where FileName in~ ("npm", "npm.cmd", "pnpm", "pnpm.cmd", "pnpm.exe", "bun", "bun.exe", "node", "node.exe")
| where ProcessCommandLine has_any (" -g", "--global", "global add")
| where ProcessCommandLine has_any ("http://", "https://", ".tgz", "git+", "file:")
| project Timestamp, DeviceName, AccountName, InitiatingProcessFileName, InitiatingProcessCommandLine, FileName, ProcessCommandLine
| order by Timestamp desc

Sigma

title: OpenCode Server Spawns Global Package Install From Remote Tarball
id: 7c1e4a52-3b8d-5e61-9a47-1d2f6b8c0a11
status: experimental
description: Detects the OpenCode process (opencode serve / opencode web) spawning npm, pnpm or Bun with a global install of a remote tarball or URL package specifier, the GHSA-632h-h47v-g4x4 /global/upgrade exploit chain.
references:
    - https://github.com/anomalyco/opencode/security/advisories/GHSA-632h-h47v-g4x4
    - https://securitylabs.datadoghq.com/articles/opencode-upgrade-remote-code-execution/
    - https://mend.io/vulnerability-database/WS-2026-0073/
author: Threadlinqs Team
date: 2026-11-12
tags:
    - attack.initial-access
    - attack.t1190
    - attack.t1195.002
    - attack.execution
    - attack.t1203
logsource:
    category: process_creation
    product: windows
detection:
    selection_parent:
        ParentCommandLine|contains: 'opencode'
    selection_pm:
        CommandLine|contains:
            - 'npm'
            - 'pnpm'
            - 'bun'
    selection_global:
        CommandLine|contains:
            - ' -g'
            - '--global'
            - ' global add'
    selection_remote:
        CommandLine|contains:
            - 'http://'
            - 'https://'
            - '.tgz'
            - 'git+'
            - 'file:'
    condition: selection_parent and selection_pm and selection_global and selection_remote
falsepositives:
    - Legitimate OpenCode self-upgrade from a private npm mirror or internal tarball host
level: high

Known false positives:

  • Legitimate OpenCode upgrade pulling from an internal npm mirror or tarball host
  • Developers manually testing OpenCode builds from a tarball URL

Tuning notes: Allowlist internal registry/mirror hostnames in target_spec. Windows/Sysmon scope for SPL; Linux/macOS hosts are covered by the KQL form (DeviceProcessEvents) and the Linux lifecycle rule TL-2026-5809-KQL-002. Fixed in OpenCode 1.18.22 (target must be semver).

8 more detection rules (Splunk SPL, Microsoft KQL, Sigma) · unlock with TL Creds. Sign up free to unlock the detection rules or query them with the Threadlinqs MCP server (Purple)
  • Browser Connection To Default OpenCode Local Server ([indicator]:4096) — Drive-by Delivery · unlock with TL Creds
  • Package Manager Global Install Spawns Shell With Download/Reverse-Shell Idioms — Post-Exploitation (Linux/macOS) · unlock with TL Creds
  • Package Manager Global Install Connects To Non-Registry Host — Remote Tarball Fetch / C2 Staging · unlock with TL Creds
  • Non-Semver [indicator] Package Specifier Passed To Package Manager — Exploitation · unlock with TL Creds
  • Inline JavaScript Evaluation In Package Manager Global Install Lifecycle Script — Post-Exploitation · unlock with TL Creds
  • Script Interpreter Resolves Callback/Tunnelling Service — C2 After Package Lifecycle Execution · unlock with TL Creds
  • Package Manager Global Install Lifecycle Script Runs Download/Execution Tradecraft — Post-Exploitation (Windows) · unlock with TL Creds
  • Package Manager Fetches Tarball From Non-Registry Host — Attacker Package Delivery (OpenCode GHSA-632h-h47v-g4x4) · unlock with TL Creds

Indicators of compromise

As of 2026-11-12, Threadlinqs Intelligence tracks 6 indicators of compromise for TL-2026-5809.

Sample indicators (1 of 6)

  • File hash: 2a36236132b0588eafbe3a16f2d271144f5a1104

Defanged, TLP:CLEAR. Full set of 6 indicators: unlock with TL Creds.

6 indicators of compromise · unlock with TL Creds. Compare plans

Technical analysis

Fixed in 1.18.22; no CVE was assigned.

GHSA-632h-h47v-g4x4 (reported by Christophe Tafani-Dereeper of Datadog Security Labs) affects the npm package opencode-ai versions 1.14.30 through 1.18.21 when OpenCode is installed via npm, pnpm or Bun. The bug was introduced by PR #24853 (merged 2026-04-29) and first shipped in v1.14.30 (2026-04-30). Installations via curl, Homebrew, Chocolatey and Scoop are not affected by the arbitrary-package path.

Root cause is a chain of three weaknesses. (1) The /global/upgrade handler accepted a user-supplied 'target' field and passed it unvalidated to the package manager's global install command. Because npm accepts remote tarball URLs as well as version numbers, the attacker can point the install at a server they control; a preinstall lifecycle script in that package then executes on the victim's machine. (2) The endpoint used a raw handler (handleRaw) that parsed the request body as JSON without checking the Content-Type header, so a body sent as text/plain from an HTML form was accepted. (3) The server did not validate the request Origin, and browsers do not subject top-level cross-origin form navigations to CORS preflight or Chrome Local Network Access restrictions, so a web page could reach the local server (default 127.0.0.1:4096).

Exploitation requires that the victim runs the OpenCode server (opencode serve or opencode web) without password authentication, or that the browser holds cached credentials for it, and that the victim visits an attacker-controlled page while the server is running. Datadog demonstrated a working proof of concept against OpenCode 1.18.21. In-the-wild exploitation is not reported in the sources. Datadog observed 82 vulnerable versions with over 647,000 npm downloads between 2026-09-17 and 2026-09-23 (about 38.9% of downloads in that period); this does not indicate unique users or how many run the server.

The fix (PR #44686, released in 1.18.22 on 2026-08-24) requires 'target' to be a valid semantic version and switches the handler to one that honors Content-Type, so text/plain requests receive HTTP 415. Datadog reported the issue on 2026-08-11; at the vendor's request public disclosure was delayed one month to 2026-09-24. The GitHub advisory rates it High (CVSS 3.1 7.5) and lists CWE-346, CWE-352 and CWE-436. Mend.io tracks it as WS-2026-0073 (CVSS v3 7.5, CVSS v4 7.7).

MITRE ATT&CK techniques by tactic:

Execution

T1059 Command and Scripting Interpreter; T1203 Exploitation for Client Execution

Initial Access

T1190 Exploit Public-Facing Application; T1195.002 Supply Chain Compromise: Compromise Software Supply Chain

Resource Development

T1608.001 Stage Capabilities: Upload Malware

Remediation

Patches

  • OpenCode 1.18.22 (PR #44686) validates target as a semantic version and enforces Content-Type (HTTP 415 for text/plain)

Immediate actions

  • Upgrade OpenCode to 1.18.22 or later
  • Stop 'opencode serve' / 'opencode web' instances running without a password until upgraded
  • Set OPENCODE_SERVER_PASSWORD on any server instance, especially if reachable beyond localhost
  • Check install method with: ls -l "$(command -v opencode)" (npm, pnpm and Bun installs are affected)

Workarounds

  • Install OpenCode via a non-npm channel (curl installer, Homebrew, Chocolatey, Scoop), which the advisory says is not affected by the arbitrary-package path
  • Do not run the OpenCode server without password authentication

Longer-term hardening

  • Avoid leaving local agent HTTP servers running while browsing untrusted sites
  • Monitor developer workstations for package-manager global installs spawned by the OpenCode process

Affected and fixed versions

  • Anomaly (anomalyco) — OpenCode (npm: opencode-ai), npm/pnpm/Bun installations
    Vulnerable versions: >=1.14.30 and <1.18.22
    Fixed in: 1.18.22

Timeline

  • PR #24853 merged into OpenCode, introducing the unvalidated /global/upgrade target behavior.
  • OpenCode v1.14.30, the first vulnerable release, is published.
  • Datadog Security Labs identifies the flaw and reports it via GitHub Security Advisories.
  • Fix PR #44686 is opened, merged and released as OpenCode 1.18.22; publication is delayed one month at the vendor's request.
  • Start of the 7-day window in which Datadog counted over 647,000 npm downloads of vulnerable versions (about 38.9% of downloads).
  • Datadog Security Labs article and GitHub advisory GHSA-632h-h47v-g4x4 published, with a public proof of concept against 1.18.21; Mend.io publishes WS-2026-0073.
  • Mend.io updates WS-2026-0073.

Sources cited

Previous and next in vulnerability

Drafted by the Threadlinqs research pipeline from 6 sources; published ; last updated —.

Threadlinqs Intelligence — Real-Time Threat Detection Platform

// threat_feed
$ sort --newest
Showing all threats

Live intelligence console

Threat level

Latest Threats