Mar 20, 2026·5 min read·48 visits
Scriban versions prior to 6.6.0 fail to enforce default recursion depth limits during template parsing and object evaluation. Deeply nested template syntax exhausts the thread stack, causing the .NET host application to terminate immediately. The vulnerability is remediated in version 6.6.0 by enforcing safe default limits on expression depth, object recursion, and output buffer size.
The Scriban templating engine prior to version 6.6.0 contains an uncontrolled recursion vulnerability in its recursive-descent parser. Attackers providing maliciously nested templates can trigger a StackOverflowException, resulting in an unrecoverable process crash and complete denial of service.
The Scriban templating engine prior to version 6.6.0 contains an uncontrolled recursion vulnerability (CWE-674). Applications parsing untrusted templates using affected versions expose an unauthenticated denial-of-service attack vector. The vulnerability originates from the engine's recursive-descent parser, which processes template syntax without enforcing default structural depth limits.
When the parser encounters specific syntactic elements, it allocates stack frames proportional to the nesting depth of the input. Without a boundary limit, malicious inputs rapidly consume the available thread stack space. This mechanism reliably triggers a process-level crash in the hosting .NET application.
The attack surface extends beyond template parsing into the object graph evaluation phase. The evaluation logic lacked default constraints on object recursion and output buffer sizes. Attackers exploiting this secondary vector induce memory exhaustion, compounding the availability impact on the host system.
Scriban implements a recursive-descent parser to evaluate template expressions. The parser relies on method recursion to handle nested syntactical structures, such as parenthesized groups or member access chains. Each nested element invokes the EnterExpression() method, adding a new frame to the execution call stack.
In versions prior to 6.6.0, the ExpressionDepthLimit property within ParserOptions was defined as a nullable integer and initialized to null. The parser logic did not perform boundary checks against the recursion depth unless developers explicitly configured a limit. Consequently, the parser unconditionally traversed maliciously nested input strings.
The .NET runtime handles thread stack exhaustion by throwing a StackOverflowException. This specific exception is non-recoverable and terminates the host process immediately without allowing exception handling blocks to execute. A separate flaw in TemplateContext.cs allowed unbounded object graph traversal during string serialization, as ObjectRecursionLimit and LimitToString defaulted to zero.
The vulnerability stems from missing default limits in configuration classes and the absence of boundary enforcement in the parsing routines. The fix spans two primary commits to enforce safety boundaries globally. The first commit (a6fe6074199e5c04f4d29dc8d8e652b24d33e3e4) establishes safe default limits within the configuration objects.
// Vulnerable state: ParserOptions.cs
public int? ExpressionDepthLimit { get; set; } = null;
// Patched state: ParserOptions.cs
public int? ExpressionDepthLimit { get; set; } = 250;The second commit (b5ac4bf30459fdc76964e3f751e16f7e96079ea7) modifies the parser itself to enforce the depth limit actively, ensuring backward compatibility for users who explicitly passed null to bypass checks.
// Patched state: Parser.Expressions.cs
private void EnterExpression() {
var limit = Options.ExpressionDepthLimit ?? 250;
if (CurrentDepth > limit) {
// Throw safe parser error instead of StackOverflowException
}
CurrentDepth++;
}Additionally, limits were applied to the evaluation context to prevent Out-Of-Memory (OOM) conditions during object resolution. The LimitToString property now caps output buffers at 1,048,576 characters (1MB), and ObjectRecursionLimit restricts graph traversal depth to 20 levels.
Exploitation requires the attacker to submit a crafted template string to an endpoint that processes input using Template.Parse(). No authentication is necessary if the application exposes template functionality to anonymous users. The attack relies solely on creating deep syntactic nesting.
The core exploitation technique leverages consecutive grouping characters. By opening thousands of parentheses without closing them, the attacker forces the parser into deep recursion. The following proof-of-concept constructs an excessively nested string that crashes the parsing process.
// Proof of Concept generating 10,000 nested layers
var templateText = new string('(', 10000) + "1" + new string(')', 10000);
Template.Parse(templateText);Upon executing Template.Parse(), the host process immediately throws a StackOverflowException. The application terminates, dropping all current connections and ceasing to process further requests. Alternative payloads include nested if statements or recursive wrap blocks to achieve identical denial-of-service conditions.
The vulnerability yields a complete loss of availability, reflected in the CVSS score of 7.5 (High). An attacker requires minimal resources to crash the targeted service. The impact is systemic, affecting the entire application hosting the Scriban engine.
The use of StackOverflowException is particularly lethal in the .NET runtime environment. Unlike standard runtime exceptions, stack overflows cannot be caught using standard try-catch blocks. The CLR enforces immediate process termination to preserve memory integrity.
Applications functioning as multi-tenant platforms or rendering user-supplied markdown and templates are highly susceptible. The secondary OOM vectors similarly result in process termination or extreme performance degradation, requiring manual restarts of the affected service containers or processes.
The primary remediation strategy requires upgrading the Scriban NuGet package to version 6.6.0 or later. This release introduces enforced safe defaults for both parsing depth and evaluation buffer sizes. The update does not introduce breaking API changes, allowing seamless integration for existing implementations.
If immediate patching is not technically feasible, developers must manually enforce configuration limits before parsing untrusted input. The ParserOptions and TemplateContext objects must be instantiated with explicit boundaries prior to invocation.
// Manual Mitigation Pattern
var options = new ParserOptions { ExpressionDepthLimit = 250 };
var context = new TemplateContext {
ObjectRecursionLimit = 20,
LimitToString = 1048576
};Security teams should implement static code analysis rules to detect instances of Template.Parse() or Template.Render() operating without custom configuration limits on older package versions. Monitoring for unexpected process terminations accompanied by stack overflow event logs serves as a reactive detection mechanism.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
Scriban Alexandre Mutel (xoofx) | < 6.6.0 | 6.6.0 |
| Attribute | Detail |
|---|---|
| Vulnerability Class | Uncontrolled Recursion (CWE-674) |
| Attack Vector | Network (Remote) |
| CVSS v3.1 Score | 7.5 (High) |
| Impact | Denial of Service (Process Crash) |
| Authentication Required | None |
| Exploit Status | Proof of Concept Available |
The program does not properly control the amount of recursion that takes place, consuming excessive resources, such as allocated memory or the program stack.
The @jhb.software/payload-cloudinary-plugin exposes an endpoint that performs unvalidated cryptographic signing of Cloudinary API parameters, allowing authenticated users with minimal privileges to forge valid signatures for arbitrary actions. This flaw allows attackers to overwrite remote storage assets, execute unauthorized file uploads, alter asset visibility parameters, trigger SSRF webhooks, and perform directory traversal within Cloudinary repositories.
A Server-Side Request Forgery (SSRF) and Bearer Token Exfiltration vulnerability exists in the @merill/lokka (Lokka) Model Context Protocol (MCP) server prior to version 2.1.2. The server constructed Azure Resource Manager request URLs by concatenating user-controlled path parameters directly into destination request strings. By injecting authority-redefinition characters, an attacker can manipulate URL parsing to execute a host-escape attack, forcing the server to send high-privilege Azure Resource Manager (ARM) Bearer tokens to an external attacker-controlled host. This allows complete administrative access to the associated Azure subscriptions.
A directory traversal and symlink following vulnerability exists in Pydantic Settings when using the NestedSecretsSettingsSource with nested subdirectory lookups enabled. An attacker capable of writing to the secrets directory can bypass size limitations, read arbitrary host files, or cause a denial-of-service condition via cyclic symlinks.
A Server-Side Request Forgery (SSRF) vulnerability exists in SurrealDB's Identity & Access Management (IAM) module prior to version 3.1.5. When configuring JSON Web Key Set (JWKS) URLs for token verification, the remote fetcher follows HTTP redirects by default without validating redirect targets against configured network capabilities. This allows high-privileged users to bypass network access limits and perform blind port scanning of internal network resources.
A local file disclosure vulnerability exists in SurrealDB's full-text search capabilities, allowing authenticated users with database EDITOR or OWNER roles to read arbitrary files from the host system filesystem. This occurs by abusing the mapper() filter inside a DEFINE ANALYZER statement to point to system files.
SurrealDB versions 3.0.0 through 3.1.4 contain an information exposure vulnerability (CWE-203) where the query planner optimizes sorted queries using indexes on fields with field-level SELECT restrictions. Because the query planner performs index-based sorting before enforcing permission-based redaction, unauthorized users can observe the physical order of returned rows to deduce the relative values of protected fields.