FlawOpen

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

● Microsoft AutoGen project · CWE-1385 / CWE-306 / CWE-78 · 2026-06-18 · उच्च
सुरक्षा अनुसंधान · FlawOpen

AutoJack: AutoGen Studio की RCE शोध श्रृंखला

Microsoft के AutoJack शोध ने AutoGen Studio के development build में local MCP RCE chain पाई। रिलीज़ से पहले ठीक हुई; PyPI package में नहीं आई।[1], [2]

💡 आसान भाषा में (ELI5)

एक ऐसी शोध प्रयोगशाला की कल्पना करें जहाँ सहायक आगंतुकों की पर्चियाँ पढ़ता है। उसी इमारत में काम करने के कारण उसे नियंत्रण कक्ष में जाने दिया जाता है। वहाँ reception सामान्य पहचान-जाँच छोड़ देता है और आगंतुक की पर्ची यह चुन सकती है कि कौन-सा औज़ार शुरू हो। AutoJack ने इन रास्तों को जोड़ा: browsing agent ने अविश्वसनीय कंटेंट दिखाया, वह AutoGen Studio के स्थानीय MCP control plane तक पहुँचा, और caller की settings से child process शुरू हो सकता था। control plane पर authentication लागू करें, startup settings को WebSocket URL से हटाएँ और assistant को developer workstation से अलग रखें। Microsoft के अनुसार PyPI release से पहले upstream branch में सुधार हुआ। यह रिपोर्ट pre-release source code पर है, ग्राहकों को जारी किसी प्रभावित version पर नहीं।[1]

इस पेज के मुख्य शब्द

AutoJack
AutoGen Studio के development build में प्रदर्शित chain के लिए Microsoft का नाम। रिपोर्ट कहती है कि प्रभावित MCP route को प्रकाशित PyPI package में शामिल होने से पहले ठीक किया गया।[1], [2]
Loopback / localhost
उसी host पर सेवाओं तक पहुँचने वाला network interface। यह बाहरी नेटवर्क से पहुँच सीमित करता है, लेकिन agent browser जैसी local processes को उसी host की अन्य services से अलग नहीं करता।[1]
WebSocket Origin validation
WebSocket handshake के दौरान server द्वारा Origin header की जाँच। Microsoft ने पाया कि परीक्षण किए गए agent flow में यह जाँच अकेले rendered page को local MCP service तक पहुँचने से नहीं रोकती थी।[1], [3]
StdioServerParams
AutoGen की MCP stdio configuration, जिसमें server process शुरू करने वाला program और arguments होते हैं। रिपोर्ट में route इन्हें WebSocket URL parameter से decode करता था।[1], [2], [5]
Confused deputy
किसी privileged component को अविश्वसनीय पक्ष के लिए अपने अधिकार इस्तेमाल करने के लिए बहकाया जाता है। यहाँ browsing agent और local Studio service page content को host पर process शुरू करने से जोड़ते थे।[1]

फ्रेमवर्क मैपिंग

घटना का समयक्रम (Timeline)

2026-06-18 से पहले

Microsoft ने MSRC को व्यवहार की सूचना दी; AutoGen maintainers ने commit b047730 में upstream branch को मजबूत किया। रिपोर्ट के अनुसार प्रभावित MCP WebSocket route PyPI package में प्रकाशित नहीं हुआ था।[1], [2]

2026-06-18

Microsoft ने AutoJack research और mitigation guidance प्रकाशित की। इसमें नियंत्रित स्थानीय demonstration बताया गया है, ग्राहकों पर पुष्टि किया गया हमला नहीं।[1]

हमले का चरण-दर-चरण प्रवाह

चरण 1

Agent को अविश्वसनीय कंटेंट ब्राउज़ करने को मिलता है

Prompt, retrieved page या अन्य अविश्वसनीय input से AutoGen browsing agent, AutoGen Studio चलाने वाली उसी workstation पर attacker-controlled page दिखाता है।[1]

चरण 2

दिखाया गया page local MCP WebSocket तक पहुँचता है

Microsoft के परीक्षण में page script localhost पर Studio MCP endpoint से जुड़ सका। Origin allowlist ने local agent browser द्वारा render किए गए code को control plane से अलग नहीं किया।[1], [3]

चरण 3

MCP route सामान्य authentication middleware को छोड़ता है

प्रभावित middleware ने यह मानकर /api/mcp paths छोड़े कि WebSocket handler स्वयं authentication करेगा। Microsoft के अनुसार handler में यह जाँच नहीं थी।[1], [4]

चरण 4

WebSocket query server parameters तय करता है

Development route ने URL से server_params decode करके StdioServerParams बनाया। इसके बाद MCP stdio transport ने command और args से child process शुरू किया।[1], [2], [5]

चरण 5

Chain host account तक पहुँचती है

स्थानीय Studio process अपने OS privileges से configured child process शुरू करता है। Microsoft ने नियंत्रित local PoC में इसे दिखाया और कहा कि route PyPI package में जारी नहीं हुआ था।[1], [2]

सोर्स कोड: कमज़ोर बनाम सुरक्षित कार्यान्वयन

असुरक्षित उदाहरण caller-controlled startup settings को parse करता है, लेकिन जानबूझकर कोई process शुरू नहीं करता। Upstream fix ने settings को WebSocket query से हटाकर server-side one-time session state में रखा और MCP routes पर authentication फिर लागू की। यह defensive pattern expiry, size bound, concurrent access lock और executable allowlist जोड़ता है; example name को स्वीकृत MCP binaries से बदलें। यह Origin validation या 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:
    # डेवलपमेंट रूट 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 सत्यापित middleware से आना चाहिए, अनुरोध डेटा से कभी नहीं।
    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]

इंजीनियरिंग और सिस्टम सुरक्षा चेकलिस्ट

स्रोत