Cline's Kanban server: a cross-origin WebSocket hijack path to RCE
A May 2026 disclosure shows Cline's local Kanban WebSocket server ships with no origin check — any website a developer visits can read the workspace and inject commands into a running agent.
What is this?
On May 8, 2026, a GitHub Security Advisory disclosed a cross-origin WebSocket hijacking flaw in the Kanban board that ships with the Cline coding agent. The kanban npm package, launched by the cline CLI, starts a local WebSocket server on 127.0.0.1:3484 and accepts every incoming connection without checking the Origin header or requiring any token. NVD published the entry on June 1, 2026 and rated it critical (CVSS 9.6); CISA’s ADP enrichment on June 3 flagged it as proof-of-concept exploitable with total technical impact. As of publication there was no patched release — every version up to and including Cline 2.13.0 is affected.
The technique is old, the target is new. Cross-Site WebSocket Hijacking (CSWSH) has been in the OWASP canon for years. What changed is what sits behind the socket: an autonomous coding agent with a live terminal and full filesystem context, reachable from any browser tab.
How it works
Browsers enforce the same-origin policy on fetch and XMLHttpRequest, but WebSocket upgrade requests are not subject to CORS. A page at https://any-site.example can open ws://127.0.0.1:3484/... and the browser will complete the handshake. The only thing that should stop it is the server validating the Origin header on upgrade — and Cline’s Kanban server did not.
Three endpoints were exposed with neither origin validation nor authentication. A runtime state socket streams a full workspace snapshot the moment a client connects: filesystem paths, git branch, task titles and descriptions, and live agent chat messages. A terminal I/O socket writes raw bytes straight into the agent’s pseudo-terminal. A control socket can stop active tasks. Conceptually, the vulnerable upgrade handler looked like this:
server.on("upgrade", (request, socket, head) => {
// Path is checked, but the Origin header is never validated,
// so a cross-origin page completes the handshake.
runtimeStateHub.handleUpgrade(request, socket, head, { ... });
});
From there the chain is: connect from a malicious page and read the streamed workspace snapshot; watch for a task_sessions_updated event that marks an agent as running; then send text to the terminal socket ending in a carriage return. The agent treats the injected text as user input, and the \r submits it exactly as if the developer had pressed Enter — turning text injection into command execution as [REDACTED shell command]. No user interaction is needed beyond having Kanban open and visiting the wrong page.
Example prompt
The snippet below shows why the hijack works: the local server completes the WebSocket handshake without checking the Origin header, so a page in any tab can reach it. The payload is redacted — this is for defenders.
# Cross-Site WebSocket Hijack on a local agent server (illustrative, defensive)
# A page the developer visits opens a socket the browser never blocks:
ws = connect("ws://127.0.0.1:3484/[terminal-endpoint]")
# Injected text + a carriage return would submit as agent input:
ws.send("[hidden instruction]\r") # [payload redacted]
# Root cause: the server accepts the upgrade without checking Origin.
# Defense: validate the Origin header on every WebSocket upgrade,
# require a per-session token, and bind to a random loopback port.
Why it matters
This is a concrete instance of a pattern that keeps recurring as agents move onto the desktop: a powerful local service, bound to loopback, treated as trusted because “only localhost can reach it.” Loopback is not a security boundary against a browser the user is already running. Any ad frame, compromised dependency, or malicious link can host the JavaScript. The confidentiality hit alone — repo paths, unreleased branch names, task prompts, and the agent’s own chat — is a serious leak for developers working on private code, and the terminal-injection step escalates it to remote code execution on macOS, Linux, and Windows alike.
Defenses
The advisory’s remediation guidance generalizes to any local agent server:
- Validate the
Originheader on every WebSocket upgrade. Reject anything that is not the agent’s own UI origin. This is the single fix that closes the class. - Require an unguessable session token. Generate a random secret at server startup, hand it to the legitimate UI at page load, and demand it as a connection parameter. Cross-origin pages cannot guess it.
- Authenticate the sensitive sockets independently. Terminal I/O and task-control channels should verify the caller, not assume loopback equals trusted.
- Bind to a random high port and/or a unix domain socket where feasible, and never stream secrets in an unsolicited snapshot on connect.
- As a user, until you are on a fixed build: avoid running the Kanban board while browsing untrusted sites, and treat any localhost agent UI as internet-reachable.
Status
| Item | Value |
|---|---|
| Reference | CVE-2026-44211 / GHSA-5c57-rqjx-35g2 |
| Class | CSWSH (CWE-1385) + Missing Auth (CWE-306) |
| Affected | Cline <= 2.13.0 (kanban npm package) |
| CVSS 3.1 | 9.6 Critical (AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H) |
| Disclosed | GitHub advisory 2026-05-08; NVD 2026-06-01 |
| Patch | None available at time of disclosure |
| Exploitation | Public PoC (CISA SSVC: total technical impact) |
Key dates: May 5, 2026 — CVE reserved. May 8, 2026 — GitHub advisory published. June 1, 2026 — NVD entry. June 3, 2026 — CISA ADP enrichment.