threat intelligence

CVE-2026-73299: A Critical RCE in Microsoft Prompty's Template Renderer

September 11, 2026 CrowdSOC Team 8 min read
CVE-2026-73299: A Critical RCE in Microsoft Prompty's Template Renderer
← back to insights
CrowdSOC Team · September 11, 2026

If your organization has any generative AI initiative underway, whether that's a customer-facing chatbot, an internal copilot, or an agent framework built on Azure AI Foundry, there is a reasonable chance a prompt file somewhere in that stack looks like ordinary text: a markdown-style document with some instructions and a few placeholders for user input. That's the whole idea behind Prompty, a Microsoft-backed open format for packaging and running LLM prompts. It's meant to be simple, portable, and easy for a developer or even a non-developer to edit.

That simplicity is exactly what makes CVE-2026-73299 worth a few minutes of a leadership team's attention. A flaw in the way Prompty's TypeScript engine processes those "just text" prompt files means that, under the wrong conditions, opening a prompt file can be equivalent to running a program the attacker wrote. The vulnerability carries the maximum possible CVSS score, 10.0, and a patch has already been published. This article explains what happened, who should care, and what to do about it.


What is Prompty, and why does a prompt file matter?

Prompty is Microsoft's open specification for storing an LLM prompt, its model configuration, and its input variables as a single, version-controllable file (with a .prompty extension). It's used across Python, .NET, and TypeScript/Node.js projects, and it's a supported asset type inside Microsoft Foundry (formerly Azure AI Foundry) and Prompt Flow. The pitch is straightforward: instead of hardcoding a prompt string inside application code, developers keep it in its own file, which makes prompts easier to test, review, and swap out.

Under the hood, a .prompty file isn't static text. It's a template, rendered at runtime using a templating engine called Nunjucks so that variables like a user's question can be inserted into the prompt before it's sent to the model. Templating engines are common and generally safe when the template itself comes from a trusted source, such as a developer on your own team. The risk appears when a template can come from somewhere else: a community prompt library, a cloned repository, a file a user uploads, or content an LLM itself generates and later hands back to the renderer.

CVE-2026-73299 is exactly that scenario. It affects the TypeScript implementation of Prompty (the npm package @prompty/core) and allows a specially crafted .prompty template to break out of the prompt and execute arbitrary JavaScript in the Node.js process that's rendering it.


The disclosure

The vulnerability was reported to Microsoft's Prompty maintainers through GitHub's coordinated disclosure process, credited to security researcher lexdotdev. Microsoft published the advisory, tracked as GHSA-w28w-gp39-m4p6, on July 20, 2026, alongside the fix in pull request #404. CVE-2026-73299 subsequently appeared in the National Vulnerability Database's public feed on August 12, 2026, which is when broader vulnerability-tracking coverage picked it up.

We were not able to identify a public, functional proof-of-concept exploit or any evidence of exploitation in the wild for this specific CVE at the time of writing. That's a meaningfully different situation than some of the vulnerabilities we've covered in past posts, where a PoC was public and attackers were probing within days. Here, the underlying bug class, server-side template injection, is well understood and not hard to weaponize once you know the affected code path, so treat the absence of a known exploit as a head start, not a reason to deprioritize the patch.


What is CVE-2026-73299?

CVE-2026-73299 is a code injection vulnerability, classified under CWE-94 (Code Injection) and CWE-1336 (Improper Neutralization of Special Elements Used in a Template Engine). It carries a CVSS v3.1 score of 10.0 (Critical), with a vector of AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H: exploitable over the network, low complexity, no privileges or user interaction required, and a scope change, meaning the impact extends beyond the vulnerable component itself into the full confidentiality, integrity, and availability of the host process.

The root cause

Prompty's TypeScript renderer uses Nunjucks to evaluate the body of a .prompty template. Nunjucks, like most JavaScript templating engines, resolves expressions such as {{ variable.property }} by looking up properties on whatever object is passed in. The affected version of the renderer placed no restrictions on which properties a template was allowed to look up, and no restrictions on calling functions that a lookup returned.

That matters because every JavaScript object exposes standard properties like constructor and __proto__, which lead back to core language features, including the Function constructor. A template author who can reach those properties can construct and invoke arbitrary code, in the same style as the well-known Nunjucks/JavaScript sandbox-escape pattern:

{{ "".constructor.constructor("return process")().mainModule.require("child_process").execSync("id") }}

An expression along these lines walks from an ordinary string, up through its constructor, back down into the Function constructor, and out to the process object, from which the attacker can reach Node.js's child_process module and run operating system commands. Because Prompty templates are frequently authored outside the application's own codebase, by design, the renderer was effectively treating untrusted input as executable code.

The fix

The patch, released in @prompty/core 0.1.5 and 2.0.0-beta.5, closes both halves of the path: it restricts member lookups so that unsafe properties like constructor, prototype, and __proto__ can no longer be traversed from within a template, and it blocks template-originated function calls outright. Ordinary Prompty functionality, variable interpolation, conditionals, loops, and access to a template's own supplied data, continues to work unchanged.

What an attacker can do

Exploitation requires only that an attacker can supply or influence the content of a .prompty file that gets rendered by a vulnerable TypeScript runtime. No authentication, no user interaction beyond the render itself, and no prior foothold are required. Once the template is rendered, the injected code runs with whatever privileges the Node.js host process has, which in a typical deployment could include access to API keys, database credentials, internal network reachability, or the ability to read and write files on disk.

Because the vulnerable component is a library embedded inside a host application, rather than a standalone network service, the practical severity in any given environment depends heavily on where that application's prompt content comes from and what the hosting process is permitted to do.


Who is affected?

Product Affected Versions Fixed In
@prompty/core (npm, TypeScript renderer) <= 0.1.4 0.1.5
@prompty/core (npm, TypeScript renderer, 2.x beta line) <= 2.0.0-beta.4 2.0.0-beta.5

This CVE is specific to the TypeScript/Node.js implementation of Prompty. The Python and .NET/C# implementations of Prompty use different rendering code paths and are not affected by this particular flaw; if your team uses Prompty from Python or .NET, this specific CVE doesn't apply to you, though it's worth confirming which runtime your project actually depends on rather than assuming.

Unlike the internet-facing server software we've covered in previous posts, Prompty is a library that gets embedded inside other applications, so there's no equivalent of an internet-wide scan count to point to here. Exposure instead tracks adoption: any organization building generative AI features, agents, or internal tooling on top of @prompty/core in Node.js, whether directly through Microsoft Foundry, Prompt Flow, VS Code tooling, or a custom integration, should treat this as applicable until proven otherwise.

Where the risk is concentrated

Applications that load prompts from outside the development team. If your product allows end users, customers, or third-party contributors to supply or customize .prompty templates (a "bring your own prompt" feature, a prompt marketplace, a plugin system), you are in the highest-risk category.

Multi-tenant AI platforms. Any platform that renders prompt templates on behalf of different tenants and shares a Node.js process to do so should treat this as an urgent item; one tenant's malicious template could compromise the host process serving everyone.

Pipelines that consume LLM-generated or LLM-modified prompts. Agentic workflows where one model's output is fed back into a Prompty template for a subsequent step create a path where the attacker doesn't need direct access to your systems at all, only the ability to influence content that eventually flows into the renderer.

Teams that clone community or third-party .prompty files. Prompt libraries and example repositories are common in this ecosystem; a template pulled from an untrusted source and rendered without review carries the same risk as any other untrusted code.

Internal, single-developer prototypes where every .prompty file is authored and reviewed by your own team carry meaningfully lower risk, since the attacker would need to compromise that trusted authoring pipeline first, but "lower risk" is not "no risk," particularly if those prototypes have a habit of becoming production services.


What should you do?

1. Determine whether you're affected

Check whether your project depends on the TypeScript Prompty renderer and which version:

npm ls @prompty/core

If the installed version is 0.1.4 or earlier, or 2.0.0-beta.4 or earlier, you're running a vulnerable release.

2. Upgrade immediately

# 0.x line
npm install @prompty/core@0.1.5

# 2.x beta line
npm install @prompty/core@2.0.0-beta.5

# Confirm the installed version
npm ls @prompty/core

Restart any Node.js services that load the package after upgrading, so they pick up the patched renderer rather than continuing to run from a cached build.

3. Audit where your .prompty templates come from

Even after patching, it's worth taking stock of every source your application pulls .prompty files from: your own repository, a database, an object store, a plugin directory, or a third-party feed. Treat any source you don't fully control as untrusted, and prefer to render only templates that have gone through your normal code review process.

4. If you cannot patch immediately

Isolating the service that renders Prompty templates is a reasonable interim step. Run it in a container or sandboxed process with minimal filesystem access, no credentials it doesn't strictly need, and restricted egress, so that even a successful exploit has little to reach. This isn't a substitute for the upgrade, but it reduces the blast radius while you schedule the change.

5. Review other Prompty advisories

Prompty has had more than one security fix in recent months; a separate, lower-severity issue involving ${file:...} path expansion in .prompty frontmatter (allowing local file reads) was fixed earlier, in version 2.0.0-beta.2. If you're upgrading to address CVE-2026-73299, confirm you're landing on a release that also includes that earlier fix, rather than jumping straight to a version that only addresses one of the two.


Detection

Because this vulnerability results in arbitrary code execution inside a Node.js process, the most useful detection signals sit at the process and file level rather than in application logs:

File and template auditing. Scan any repositories, prompt stores, or upload directories for .prompty files whose bodies reference constructor, __proto__, or prototype inside template expression delimiters ({{ }} or {% %}).

Process behavior. Alert on Node.js processes that spawn shells (sh, bash, cmd.exe, powershell.exe) or child processes shortly after loading or rendering Prompty content; this is not normal behavior for a prompt-rendering step.

Network behavior. Watch for unexpected outbound connections originating from a Node.js host shortly after a template render, which could indicate data exfiltration or a reverse shell.

Inventory. Maintain a current inventory of which services depend on @prompty/core and at what version, so that the next Prompty advisory (and there may well be one) can be triaged quickly rather than starting from scratch.


A broader note on prompt files as an attack surface

CVE-2026-73299 is a useful reminder that as generative AI tooling matures, the files and formats built to make that tooling easier to use, prompt templates, agent configurations, plugin manifests, are themselves becoming a legitimate attack surface. They often look like plain text or simple configuration, which can make it easy to underestimate what happens when they're rendered or interpreted by code. The same scrutiny your organization already applies to executable code and server configuration is worth extending to anything that gets templated, parsed, or evaluated as part of an AI pipeline, even when it doesn't look like code at first glance.


Summary

CVE CVE-2026-73299
Component Prompty TypeScript renderer (@prompty/core, npm)
Type Code Injection / Server-Side Template Injection leading to Remote Code Execution
CVSS Score 10.0 (Critical, v3.1)
CWE CWE-94, CWE-1336
Attack vector Network; no authentication or user interaction required
Reported by lexdotdev, via GitHub coordinated disclosure
GitHub advisory GHSA-w28w-gp39-m4p6, published July 20, 2026
Affected @prompty/core <= 0.1.4 and <= 2.0.0-beta.4 (TypeScript/Node.js implementation only)
Not affected Prompty's Python and .NET/C# implementations
Full fix Upgrade to @prompty/core 0.1.5 or 2.0.0-beta.5
Public PoC / active exploitation? None identified at time of writing

If you need help inventorying which of your services depend on Prompty, auditing where your prompt templates originate, or reviewing your broader generative AI attack surface, get in touch. As AI tooling becomes a bigger part of production environments, the components supporting it deserve the same rigor as everything else in your stack.

← all insights