Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-73299

CVE-2026-73299: Prompty TypeScript Nunjucks RCE Vulnerability

CVE-2026-73299 is a remote code execution flaw in Prompty's TypeScript Nunjucks renderer that allows attackers to execute arbitrary JavaScript via template injection. This article covers the technical details, affected versions, and patches.

Published:

CVE-2026-73299 Overview

CVE-2026-73299 is a code injection vulnerability [CWE-94] in Microsoft Prompty, a markdown file format (.prompty) used for large language model (LLM) prompts. The TypeScript Nunjucks renderer evaluated untrusted .prompty template bodies with unrestricted JavaScript member access. An attacker-controlled template can traverse constructor and prototype properties to execute arbitrary JavaScript in the host Node.js process. The issue affects Prompty versions prior to 0.1.5 and 2.0.0-beta.5.

Critical Impact

A malicious .prompty template loaded by a vulnerable renderer achieves remote code execution in the host Node.js process, with scope change beyond the vulnerable component.

Affected Products

  • Microsoft Prompty TypeScript renderer versions prior to 0.1.5
  • Microsoft Prompty TypeScript renderer versions prior to 2.0.0-beta.5
  • Applications embedding the vulnerable promptyjs Nunjucks renderer

Discovery Timeline

Technical Details for CVE-2026-73299

Vulnerability Analysis

Prompty renders .prompty template bodies using the Nunjucks templating engine. The renderer was configured without restrictions on JavaScript member access. As a result, template expressions could reach JavaScript object internals such as __proto__, constructor, and prototype. From there, an attacker can pivot to Function or other host globals and execute arbitrary code. This is a classic sandbox escape pattern in server-side JavaScript templating engines.

The vulnerability sits in the code injection class [CWE-94]. Because Prompty templates are often authored externally or supplied by upstream data sources, the renderer effectively treats untrusted input as executable code.

Root Cause

The root cause is unrestricted memberLookup and callWrap behavior in the Nunjucks runtime used by Prompty. Nunjucks by default allows expressions like {{ obj.constructor.constructor('return process')() }} to walk the JavaScript prototype chain. Without an allow-list or explicit blocking of unsafe property names, the renderer exposed the entire Node.js runtime to template authors.

Attack Vector

Exploitation requires an attacker to supply or influence a .prompty template body that will be rendered by a vulnerable Prompty TypeScript runtime. No authentication or user interaction is required at the network layer if the host application accepts remote prompt content. Once rendered, the attacker-controlled expression executes in the same Node.js process as the host application.

The fix restricts member access and blocks function calls originating from the template. Source: Microsoft Commit e4a0ebf.

typescript
type NunjucksRuntime = {
  memberLookup: (object: unknown, property: unknown) => unknown;
  callWrap: (callable: unknown, name: string, context: unknown, args: unknown[]) => unknown;
};

const UNSAFE_PROPERTIES = new Set(["__proto__", "constructor", "prototype"]);

const env = new nunjucks.Environment(null, {
  autoescape: false,
  throwOnUndefined: false,
});

function safeMemberLookup(object: unknown, property: unknown): unknown {
  if (typeof property === "string" && UNSAFE_PROPERTIES.has(property)) {
    throw new Error(`Unsafe template member access: ${property}`);
  }

  if (
    (typeof property !== "string" && typeof property !== "number") ||
    object === null ||
    typeof object !== "object"
  ) {
    return undefined;
  }

  const descriptor = Object.getOwnPropertyDescriptor(object, property);
  return descriptor !== undefined && "value" in descriptor ? descriptor.value : undefined;
}

The companion patch in promptyjs additionally rejects any template-originated function call. Source: Microsoft Commit f5c57c9.

typescript
function safeCallWrap(_callable: unknown, name: string, _context: unknown, _args: unknown[]): never {
    throw new Error(`Template function calls are not allowed: ${name}`);
}

Detection Methods for CVE-2026-73299

Indicators of Compromise

  • .prompty files containing Nunjucks expressions that reference constructor, __proto__, or prototype
  • Template expressions invoking Function, process, require, or child_process through member chains
  • Unexpected child processes spawned by the Node.js host that loads Prompty templates
  • Outbound network connections from Node.js processes shortly after template rendering

Detection Strategies

  • Scan repositories and prompt stores for .prompty files whose bodies contain the substrings constructor, __proto__, or prototype inside {{ }} or {% %} delimiters
  • Alert on Node.js processes that spawn shells (sh, bash, cmd.exe, powershell.exe) shortly after loading Prompty content
  • Inventory installed @microsoft/prompty and promptyjs package versions and flag any below 0.1.5 or 2.0.0-beta.5

Monitoring Recommendations

  • Log all sources of .prompty template input, including remote fetches, user uploads, and third-party registries
  • Enable Node.js process-level auditing to record child_process.spawn and eval-family invocations
  • Forward endpoint process telemetry to a centralized analytics platform for behavioral correlation across the fleet

How to Mitigate CVE-2026-73299

Immediate Actions Required

  • Upgrade Prompty to version 0.1.5 or 2.0.0-beta.5 or later immediately
  • Audit all .prompty template sources and remove any templates from untrusted origins
  • Restart Node.js host processes after upgrading to ensure the patched renderer is loaded
  • Review the GitHub Security Advisory GHSA-w28w-gp39-m4p6 for release-specific guidance

Patch Information

Microsoft addressed the vulnerability in Prompty 0.1.5 and 2.0.0-beta.5. The patches introduce a safeMemberLookup that blocks access to __proto__, constructor, and prototype, and a safeCallWrap that rejects template-originated function calls. Refer to Microsoft Pull Request #404, Microsoft Pull Request #405, and the TypeScript 2.0.0-beta.5 release.

Workarounds

  • Treat all .prompty template bodies as untrusted input and render them only from vetted, version-controlled sources until patched
  • Isolate services that render Prompty templates in dedicated containers with minimal filesystem, network, and credential access
  • Apply egress network controls to Node.js hosts that process LLM prompt content to limit post-exploitation reach
bash
# Upgrade the vulnerable packages to the patched release
npm install @microsoft/prompty@0.1.5

# Or, for the 2.x branch
npm install @microsoft/prompty@2.0.0-beta.5

# Verify installed versions
npm ls @microsoft/prompty promptyjs

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.