FlawOpen

flawopen.com/Incidents/microsoft-autogen-studio-autojack-agent-rce-june-2026

● Microsoft AutoGen project · CWE-1385 / CWE-306 / CWE-78 · 2026-06-18 · Alta
Pesquisa · FlawOpen

AutoJack: cadeia de RCE de pesquisa no AutoGen Studio

Pesquisa da Microsoft identificou RCE local via MCP no build de desenvolvimento do AutoGen Studio. Corrigida antes do lançamento, não chegou ao PyPI.[1], [2]

💡 Explicação em Linguagem Simples (ELI5)

Imagine um laboratório onde um assistente lê bilhetes de visitantes. O assistente entra na sala de controle porque trabalha no mesmo prédio. A recepção dispensa a verificação normal de identidade nessa sala, e um bilhete de visitante pode escolher qual ferramenta será iniciada. O AutoJack combinou esses atalhos: um agente de navegação renderizava conteúdo não confiável, esse conteúdo alcançava o plano de controle MCP local do AutoGen Studio e as configurações fornecidas pelo solicitante podiam levar à criação de um processo filho. A lição é autenticar a sala de controle, tirar as configurações de inicialização das URLs WebSocket e isolar o assistente da estação de trabalho do desenvolvedor. A Microsoft afirma que a falha foi corrigida na branch upstream antes de uma versão PyPI. A análise trata de código pré-lançamento, não de uma versão de clientes afetada.[1]

Conceitos Centrais e Termos

AutoJack
Nome dado pela Microsoft a uma cadeia demonstrada em uma versão de desenvolvimento do AutoGen Studio. O relatório afirma que a rota MCP afetada foi corrigida antes de aparecer em um pacote PyPI publicado.[1], [2]
Loopback / localhost
Interface de rede que alcança serviços no mesmo host. Ela limita o acesso pela rede externa, mas não isola processos locais, como o navegador de um agente, de outros serviços naquele host.[1]
Validação de Origin em WebSocket
Verificação feita pelo servidor do cabeçalho Origin durante o handshake WebSocket. A Microsoft constatou que, no fluxo de agente testado, essa verificação sozinha não impedia a página renderizada de alcançar o serviço MCP local.[1], [3]
StdioServerParams
Configuração stdio do MCP no AutoGen, incluindo o programa e os argumentos usados para iniciar um processo servidor. A rota relatada decodificava essa configuração de um parâmetro da URL WebSocket.[1], [2], [5]
Confused deputy
Um componente privilegiado é induzido a usar sua própria autoridade em favor de alguém não confiável. Aqui, o agente de navegação e o serviço local do Studio conectavam conteúdo da página à criação de processos no host.[1]

Mapeamentos de frameworks

Linha do Tempo do Incidente

Antes de 18/06/2026

A Microsoft comunicou o comportamento ao MSRC; os mantenedores do AutoGen reforçaram a branch upstream no commit b047730. O relatório diz que a rota MCP WebSocket afetada não havia sido publicada em um pacote PyPI.[1], [2]

18/06/2026

A Microsoft publicou a pesquisa AutoJack e as orientações de mitigação. O texto descreve uma demonstração local controlada, não um ataque confirmado contra clientes.[1]

Fluxo de Ataque Passo a Paso

Passo 1

O agente recebe a tarefa de navegar por conteúdo não confiável

Um prompt, uma página recuperada ou outra entrada não confiável leva um agente de navegação AutoGen a renderizar uma página controlada pelo atacante na mesma estação que executa o AutoGen Studio.[1]

Passo 2

A página renderizada alcança o WebSocket MCP local

Na configuração testada pela Microsoft, o script da página podia se conectar ao endpoint MCP do Studio em localhost. A lista de Origin não isolava do plano de controle o código renderizado pelo navegador local do agente.[1], [3]

Passo 3

A rota MCP ignora o middleware normal de autenticação

O middleware afetado ignorava caminhos /api/mcp sob a suposição de que o handler WebSocket faria a autenticação. Segundo a Microsoft, esse handler não fazia essa verificação.[1], [4]

Passo 4

A consulta WebSocket controla os parâmetros do servidor

A rota de desenvolvimento decodificava server_params da URL em StdioServerParams. O transporte stdio do MCP usava então command e args para iniciar um processo filho.[1], [2], [5]

Passo 5

A cadeia chega à conta do host

O processo local do Studio inicia o processo filho configurado com os privilégios do próprio sistema operacional. A Microsoft demonstrou isso em uma prova de conceito local controlada e afirma que a rota não estava em pacote PyPI publicado.[1], [2]

Código-Fonte: Vulnerável vs. Seguro

O exemplo vulnerável analisa configurações de inicialização controladas pelo solicitante, mas deliberadamente não inicia processos. A correção upstream removeu as configurações da consulta WebSocket, moveu-as para uma sessão única armazenada no servidor e restaurou a autenticação nas rotas MCP. Este padrão defensivo acrescenta expiração, limite de tamanho, bloqueio concorrente e lista de executáveis permitidos; substitua o nome de exemplo pelos binários MCP aprovados. Ele não substitui validação de Origin nem isolamento do sistema operacional.[1], [2]

IMPLEMENTAÇÃO VULNERÁVEL
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:
    # A rota de desenvolvimento confiava na configuração fornecida pela URL.
    encoded = query["server_params"]
    decoded = base64.b64decode(encoded)
    return StdioServerParams(**json.loads(decoded))
PATCH SEGURO E ROBUSTO
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 deve vir de um middleware verificado, nunca dos dados da solicitação.
    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]

Lista de Verificação de Segurança para Engenharia

Fontes