Jul 18, 2026·6 min read·12 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.
CVE-2026-12243 is a path traversal vulnerability in the Natural Language Toolkit (NLTK) version 3.9.4. The flaw exists because the input validation routine fails to account for percent-encoded directory traversal sequences like '..%2f' before passing them to urllib.request.url2pathname(), which decodes them into active traversal sequences.
CVE-2026-73654 is a high-severity prototype pollution vulnerability in Trigger.dev. The flaw occurs during the handling of run-metadata updates through the PUT /api/v1/runs/:runId/metadata endpoint. Because user-supplied keys are parsed directly by the @jsonhero/path library without sanitization, an authenticated attacker with low privileges can pollute the global Object.prototype. This causes database queries via Prisma ORM to fail validation and induces unhandled exceptions in the Prometheus metrics client, resulting in a process-wide denial of service.
CVE-2026-73559 is an uncontrolled resource consumption vulnerability in the vLLM engine, specifically within the /v1/completions API endpoint, allowing authenticated attackers to cause application-level denial of service via unbounded prompt arrays.
A critical security bypass vulnerability in Argo Workflows allows authenticated attackers with workflow submission privileges to bypass 'Strict' or 'Secure' template referencing restrictions. By injecting unvalidated fields into the nested ArtifactGC configuration, attackers can execute arbitrary pod patches, leading to host namespace escape and cluster-wide privilege escalation.
A Server-Side Request Forgery (SSRF) / Confused Deputy vulnerability has been identified in Pydantic AI UI Adapters (such as VercelAIAdapter). Under certain conditions, a malicious client can supply manipulated message history with provider metadata that forces the server to resolve files within privileged cloud environments (AWS S3, Google Cloud Storage) or model providers. This occurs because the adapters deserialize client-provided metadata structures directly into UploadedFile instances without validation, which are subsequently fetched using high-privilege server credentials.
A path traversal vulnerability in the optional dashboard server of atomic-agents-stack before version 1.1.0 allows unauthenticated remote attackers to read arbitrary files from the host filesystem.