Skip to content

Security: C# Jinja2Renderer missing input sanitization (sibling of GHSA-w28w-gp39-m4p6) #432

Description

@leanworld7-netizen

Server-Side Template Injection in Prompty C# Jinja2Renderer

Summary

The C# implementation of Prompty (Prompty.Core NuGet package, v2.0.0-beta.4) uses Jinja2.NET.Template to render templates. While Jinja2.NET claims a sandboxed evaluation model, the C# renderer applies NO input sanitization equivalent to the TypeScript fix (safeMemberLookup, safeCallWrap, sanitizeInputs). This is a sibling to GHSA-w28w-gp39-m4p6 (critical SSTI in TypeScript Nunjucks renderer).

Affected Package

  • NuGet Prompty.Core version 2.0.0-beta.4 (latest)
  • Dependency: Jinja2.NET version 1.4.1

Root Cause

The TypeScript fix (commit 047756f) added three protection layers to the Nunjucks renderer:

  1. safeMemberLookup - blocks access to proto, constructor, prototype
  2. safeCallWrap - blocks all function calls from templates
  3. sanitizeInputs - recursively strips unsafe properties from input objects

The Python renderer uses ImmutableSandboxedEnvironment from jinja2.sandbox.

The C# renderer (Jinja2Renderer.cs) has NONE of these protections. Raw user inputs are passed directly into the template context without sanitization. While Jinja2.NET claims sandboxing, the renderer does not apply the additional input sanitization that was deemed necessary for the TypeScript and Python runtimes.

Vulnerable Code

File: runtime/csharp/Prompty.Core/Jinja2Renderer.cs

public Task RenderAsync(Prompty agent, string template, Dictionary<string, object?> inputs)
{
var (renderInputs, nonces) = RenderHelpers.PrepareRenderInputs(agent, inputs);
var jinja = new Jinja2.NET.Template(template);
var context = new Dictionary<string, object>();
foreach (var kvp in renderInputs)
{
if (kvp.Value is not null)
context[kvp.Key] = kvp.Value;
}
var rendered = jinja.Render(context); // NO sanitizeInputs, NO safeMemberLookup
return Task.FromResult(rendered);
}

Impact

  • Severity: High to Critical
  • CWE-1336: Improper Neutralization of Special Elements Used in a Template Engine
  • Potential RCE when processing untrusted .prompty files
  • Novel sibling of GHSA-w28w-gp39-m4p6 in a different runtime (C#/.NET)

References

  • TypeScript fix: 047756f
  • Existing advisory: GHSA-w28w-gp39-m4p6
  • C# source: runtime/csharp/Prompty.Core/Jinja2Renderer.cs
  • Python (sandboxed): runtime/python/prompty/prompty/renderers/jinja2.py

Remediation

  1. Implement input sanitization equivalent to TypeScript sanitizeInputs
  2. Verify Jinja2.NET sandbox blocks .NET reflection (GetType, Assembly access)
  3. Block unsafe property access if Jinja2.NET sandbox is insufficient

Reporter

Submitted via secure@microsoft.com per Microsoft SECURITY.md guidelines.

Severity Reassessment

After analyzing Jinja2.NET source code (FunctionCallNodeRenderer.cs), function calls from templates throw NotSupportedException for all functions except 'loop'. This means direct RCE via method calls (GetType().Assembly etc.) is NOT possible in Jinja2.NET.

However, the finding remains valid as:

  1. Attribute access ({{ obj.property }}) IS supported and unsanitized inputs may expose sensitive properties
  2. The C# renderer lacks the sanitizeInputs function that was deemed necessary for TypeScript and Python
  3. This is still a missing-defense-in-depth finding (High information disclosure)

The original report title mentioned RCE but the actual severity is High (information disclosure via unsanitized template context).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions