Jul 18, 2026·6 min read·15 visits
Microsoft Prompty loaders before 2.0.0-beta.2 are vulnerable to arbitrary file read via directory traversal, absolute paths, or symbolic link escapes within frontmatter `${file:...}` sequence expansions.
CVE-2026-53598 is a directory traversal and arbitrary file read vulnerability in Microsoft Prompty ecosystem loaders across multiple languages. Prior to version 2.0.0-beta.2, the loaders resolved `${file:...}` reference strings inside frontmatter configuration blocks without enforcing that the target file paths resided within authorized directories. This deficiency allows an attacker-controlled configuration file to read sensitive operating system and application files through absolute paths, directory traversal, or symbolic link escapes. The issue is addressed across the Python, C#, Node.js/TypeScript, and Rust ecosystems.
The Microsoft Prompty ecosystem provides cross-language runtimes designed to load and parse prompt templates stored in the .prompty file format. This format combines frontmatter configurations, containing metadata and execution parameters, with a markdown template body representing the prompt text. The parser allows developers to configure environment and file-level requirements directly inside the frontmatter parameters.
To facilitate structured prompts, the specification supports a reference expansion feature where sequence indicators like ${file:<path>} are evaluated dynamically. When the loader encounters this pattern, it resolves the designated path and embeds the file contents directly into the parsing tree. This sequence is evaluated across the Python, C#, Node.js/TypeScript, and Rust implementations.
Prior to version 2.0.0-beta.2, the implementation of the reference parser failed to perform boundary-containment checks during file resolution. This allowed any processed .prompty configuration file containing directory traversal or absolute paths to escape the authorized prompt directory. As a result, an attacker-controlled configuration file could leak sensitive operating system and application files.
The core issue resides in the dynamic reference-resolution phase of the frontmatter parser. When parsing a .prompty configuration file, the engine scans the frontmatter dictionary for any string properties matching the ${file:path} schema. Upon extraction of the path argument, the resolver constructs an absolute path on the host file system using the directory containing the active .prompty template as its base.
In vulnerable versions of the library, the reconstructed file path was passed directly to standard file-system read utilities without verifying that the resolved path remained a descendant of the prompt's source directory or an authorized boundary. Because the resolver did not assert path containment, characters like relative traversals, absolute drive identifiers, or local symbolic links were expanded literally.
This behavior allowed three exploitation patterns to succeed during the resolution phase. Relative traversals utilizing parent directories reached higher-level system paths. Absolute paths bypassed the template directory tree completely. Symbolic link escapes resolved the link targets to arbitrary system folders, bypassing logical directory sandboxes.
The fix for this vulnerability focuses on ensuring that any resolved file reference is constrained within a set of allowed directory roots. The default configurations dictate that only the directory containing the loaded .prompty template is considered a valid root.
# Python library fix implementation in prompty/core/loader.py
def _resolve_file_reference(
agent_file: Path,
reference: str,
allowed_file_roots: Sequence[str | Path] | None,
) -> Path:
"""Resolve and validate a ``${file:...}`` reference."""
# Canonicalize the parent directory of the prompt template
prompt_root = agent_file.parent.resolve()
# Establish allowed roots combining template directory and optional overrides
allowed_roots = [prompt_root, *(Path(root).resolve() for root in allowed_file_roots or ())]
candidate = Path(reference)
if not candidate.is_absolute():
candidate = prompt_root / candidate
# Resolve symlinks and parent pointers to find the real physical path
resolved = candidate.resolve()
# Validate that the resolved target lies within one of the approved roots
if not any(resolved == root or resolved.is_relative_to(root) for root in allowed_roots):
roots = ", ".join(str(root) for root in allowed_roots)
raise ValueError(
f"File reference '{reference}' resolves outside allowed roots for '{agent_file}'. Allowed roots: {roots}"
)
return resolvedComparing the vulnerable pattern to the updated logic reveals a transition to robust containment validation. The vulnerable code simply concatenated the relative path without performing .resolve() validation or testing with .is_relative_to(). The updated approach successfully blocks traversal payloads, absolute paths, and symbolic link targets resolving outside the approved boundary.
Exploitation of CVE-2026-53598 requires that an application ingest and parse a .prompty file containing an attacker-manipulated path. The attack surface typically manifests in platforms where users upload custom prompt configurations or when applications execute dynamic prompts retrieved from user-accessible sources.
An attacker supplies a template containing a payload in the metadata fields such as the description. When the application loads the configuration via load(), the parser extracts the arbitrary path from the reference sequence and reads the resource. The host application subsequently populates the parsed configuration object with the target content, exposing the sensitive data to the attacker through diagnostic logs, execution output, or UI responses.
The security impact of this vulnerability is categorized as high-severity confidential data exposure. Successful exploitation allows unauthorized, unauthenticated parties to read arbitrary files stored on the host running the vulnerable application, limited only by the host process's security permissions.
This flaw facilitates the extraction of configuration files, infrastructure-level environment variables, private SSL/TLS certificates, and application-specific secrets. In cloud-deployed applications, reading local configuration or metadata files can expose highly sensitive API tokens, database credentials, or identity access tokens. This level of exposure provides a path for horizontal escalation and broader system compromise.
While the vulnerability is restricted to read-only access and cannot directly manipulate system files or execute code, the extracted information is typically leveraged to execute subsequent attacks. Because no user interaction or authentication is required to trigger the path resolution, the exploitability vector remains simple and direct.
The primary remediation action requires upgrading all instances of the Microsoft Prompty package to version 2.0.0-beta.2 or newer across all target programming environments. Applications must specify the fixed versions within their respective package management configurations.
If legitimate configuration demands require reference expansion outside the prompt template directory, developers must explicitly define the approved directories during loading operations. The application API allows passing the optional allowed roots parameter to prevent throwing validation exceptions.
# Safe Python loading pattern with customized directory roots
from prompty import load
from pathlib import Path
# Safely load the prompt and limit traversal strictly to authorized paths
prompt = load(
"prompts/chat.prompty",
allowed_file_roots=[Path("/var/app/shared-templates")]
)Where immediate package updates are not possible, temporary mitigations include establishing strict validation rules at the application layer to verify .prompty files before loader ingestion. Restricting directory write privileges for the application's runtime process also limits the files exposed in a traversal attack.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
prompty (Python) Microsoft | < 2.0.0b2 | 2.0.0b2 |
Prompty.Core (C#) Microsoft | < 2.0.0-beta.2 | 2.0.0-beta.2 |
@prompty/core (Node.js) Microsoft | < 2.0.0-beta.2 | 2.0.0-beta.2 |
prompty (Rust) Microsoft | < 2.0.0-beta.2 | 2.0.0-beta.2 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-22 / CWE-200 |
| Attack Vector | Network (AV:N) |
| CVSS v3.1 | 7.5 (High) |
| EPSS Score | 1.057% (60.65th percentile) |
| Exploit Status | Proof-of-Concept (PoC) Available |
| Impact | Arbitrary File Read (Confidentiality: High) |
| CISA KEV | Not Listed |
The product uses external input to construct a pathname that should be within a restricted directory, but it does not properly neutralize sequences such as '..' that can resolve to a location outside of the restricted directory.
containerd is an open-source container runtime. Prior to versions 1.7.36, 2.0.13, 2.2.9, 2.3.6, and 2.4.1, a crafted OCI index graph can force very high CPU/memory usage during PullImage (before container start), causing long ContainerCreating stalls and, at larger sizes, node/runtime instability. The vulnerability occurs because containerd's image-pull descriptor graph resolution handlers processed OCI image indices and manifests recursively without enforcing boundaries on traversal depth or breadth, and without maintaining a global visited registry to count duplicate references.
An unauthenticated path traversal vulnerability exists in the Khoj AI assistant platform via the static file serving endpoint `/home/{file_path:path}`. Due to improper path sanitization when handling user input with Python's pathlib module, a remote attacker can read arbitrary files from the server's filesystem.
An argument injection vulnerability (CWE-88) in CliInvoke and AlastairLundy.CliInvoke allows local attackers to execute arbitrary system commands. By injecting double-quote characters into target file paths or arguments, attackers can terminate operating-system-level quoted boundaries and introduce new commands when shell runners are utilized.
An OS command injection vulnerability exists in the PowerShell and Cmd shell wrappers of the CliInvoke .NET library (specifically the CliInvoke.Specializations package). Under vulnerable configurations, arguments and targets are passed as a single flat string to ProcessStartInfo.Arguments, permitting double-quote breakout and execution of arbitrary secondary commands with host process privileges.
A critical-severity input validation vulnerability in the Elixir multi-party payment library `mpp` allows unauthenticated remote attackers to exhaust the transaction fee payer's wallet balance. By submitting a crafted Ethereum transaction envelope with artificially inflated gas parameters, an attacker can force the server to co-sign and commit to pay exorbitant fees, leading to severe financial loss and Denial of Service.
A critical gas draining vulnerability exists in the ZenHive mpp (Multi-Payment Protocol) library prior to version v0.6.0. By omitting validation of EIP-2930 access lists in custom 0x76 transaction envelopes, the library allows malicious clients to pad transaction payloads with dummy addresses, draining the gas sponsor's hot wallet.