flawopen.com/Incidents/microsoft-autogen-studio-autojack-agent-rce-june-2026
AutoJack: AutoGen Studio RCE Research Chain
Microsoft’s AutoJack research found a local MCP process-launch chain in AutoGen Studio’s dev build. Fixed before release, it never shipped on PyPI.[1], [2]
Imagine a research lab where an assistant reads notes from visitors. The assistant is allowed into a control room because it works in the same building. A receptionist skips the normal identity check for that room, and a note from a visitor can choose which tool the room starts. AutoJack joined those shortcuts: a browsing agent rendered untrusted page content, that content reached AutoGen Studio's local MCP control plane, and caller-supplied server settings could lead to a child process. The lesson is to authenticate the control room, keep launch settings out of WebSocket URLs, and isolate the assistant from the developer's workstation. Microsoft says this was fixed on the upstream branch before a PyPI release. The report concerns pre-release source code, not an affected customer release.[1]
Core Concepts & Subsystem Terms
AutoJack- Microsoft's name for a demonstrated chain in an AutoGen Studio development build. The report says the affected MCP route was fixed before it appeared in a published PyPI package.[1], [2]
Loopback / localhost- A network interface that reaches services on the same host. It limits remote network access, but it does not isolate local processes such as an agent's browser from other services on that host.[1]
WebSocket Origin validation- A server-side check of the browser Origin during a WebSocket handshake. Microsoft found that this check alone did not stop the tested agent-rendered page from reaching the local MCP service.[1], [3]
StdioServerParams- AutoGen's MCP stdio configuration, including the program and arguments used to start a server process. The reported route decoded these settings from a WebSocket query parameter.[1], [2], [5]
Confused deputy- A privileged component is induced to use its own authority for an untrusted party. Here, the browsing agent and local Studio service formed the bridge from page content to host process creation.[1]
Framework mappings
- CWE reference for the weakness described in this guide: CWE-78 CWE-306 CWE-1385
- OWASP GenAI 2025 — LLM06:2025 Excessive Agency
Incident Timeline
Microsoft published the AutoJack research and its mitigation guidance. It describes a controlled local demonstration, not a confirmed attack against customers.[1]
Step-by-Step Attack Flow
The agent is asked to browse untrusted content
A user prompt, retrieved page, or other untrusted input leads an AutoGen browsing agent to render an attacker-controlled page on the same workstation as AutoGen Studio.[1]
Source Code: Flaw vs. Secure Implementation
The vulnerable example parses caller-controlled launch settings but deliberately starts no process. The upstream fix moved settings out of the WebSocket query into one-time server-side session state and restored authentication for MCP routes. This defensive reference pattern adds expiry, a size bound, locking, and an executable allowlist; replace its example name with the exact approved MCP binaries. It does not replace Origin validation or OS isolation.[1], [2]
import base64
import json
from dataclasses import dataclass
@dataclass(frozen=True)
class StdioServerParams:
command: str
args: tuple[str, ...]
def params_from_websocket_query(query: dict[str, str]) -> StdioServerParams:
# The development route trusted configuration supplied in the URL.
encoded = query["server_params"]
decoded = base64.b64decode(encoded)
return StdioServerParams(**json.loads(decoded))from dataclasses import dataclass
from threading import Lock
from time import monotonic
from uuid import uuid4
@dataclass(frozen=True)
class StdioServerParams:
command: str
args: tuple[str, ...]
SESSION_TTL = 30.0
MAX_PENDING = 256
ALLOWED_COMMANDS = {"approved-mcp-server"}
pending: dict[str, tuple[float, StdioServerParams]] = {}
pending_lock = Lock()
def register_params(params: StdioServerParams, authenticated: bool) -> str:
# authenticated must come from verified middleware, never request data.
if not authenticated:
raise PermissionError("MCP control-plane authentication required")
if params.command not in ALLOWED_COMMANDS:
raise ValueError("unapproved MCP server executable")
now = monotonic()
with pending_lock:
for key, (expires, _) in list(pending.items()):
if expires <= now:
pending.pop(key, None)
if len(pending) >= MAX_PENDING:
raise RuntimeError("pending MCP session limit reached")
session_id = str(uuid4())
pending[session_id] = (now + SESSION_TTL, params)
return session_id
def consume_params(session_id: str, authenticated: bool) -> StdioServerParams:
if not authenticated:
raise PermissionError("MCP control-plane authentication required")
with pending_lock:
entry = pending.pop(session_id, None)
if entry is None or entry[0] <= monotonic():
raise ValueError("unknown or expired MCP session")
return entry[1]Engineering & System Hardening Checklist
- ✓Require authentication and authorization on every MCP control-plane route, including WebSocket handshakes; test the configured auth modes against those routes.[1], [2], [4]
- ✓Never accept process-launch configuration from a WebSocket URL or other attacker-controlled browser input; register it through an authenticated request and bind it to a short-lived, single-use server-side session.[2]
- ✓Expire pending sessions, bound their count, consume each session atomically, and reject unknown, expired, or replayed identifiers.[2]
- ✓Allowlist MCP server executables and fixed argument schemas; do not let model output or page content select arbitrary programs.[1], [5]
- ✓Keep browser agents that render untrusted pages away from privileged local control planes; block loopback access from the browser sandbox where feasible.[1], [3]
- ✓Run the agent and Studio under a dedicated low-privilege identity or disposable VM/container, and alert on unexpected child processes from agent runtimes.[1]
- ✓For AutoGen Studio source builds, use a revision at or after b047730. The Microsoft report says the affected MCP route was not included in the then-current PyPI package; verify the exact artifact you deploy rather than inferring exposure from the project name.[1], [2]
Sources
- Microsoft Security Blog — AutoJack: How a single page can RCE the host running your AI agent
- Microsoft AutoGen commit b047730 — harden MCP WebSocket endpoint
- CWE-1385: Missing Origin Validation in WebSockets
- CWE-306: Missing Authentication for Critical Function
- CWE-78: Improper Neutralization of Special Elements used in an OS Command