Mar 20, 2026·6 min read·28 visits
Scriban lacks default safe limits on string generation and object recursion. An attacker can use a simple loop within a template to generate gigabytes of string data in memory, causing an Out-of-Memory (OOM) crash.
The Scriban scripting engine is vulnerable to a Denial of Service (DoS) attack due to uncontrolled memory consumption. Attackers can execute specially crafted templates that trigger exponential string growth, leading to immediate heap memory exhaustion and process termination.
Scriban is a widely used text templating language and engine for the .NET framework, designed for parsing and rendering dynamic text blocks. Applications frequently integrate Scriban to allow users or administrators to define custom document layouts, email templates, or dynamic web content. The engine accepts template strings, compiles them into an Abstract Syntax Tree (AST), and evaluates them against a provided data context.
The vulnerability, identified as GHSA-5RPF-X9JG-8J5P, resides in the execution phase of the Scriban engine where resource constraints are not strictly enforced by default. The engine evaluates string concatenation operations within iterative structures (loops) without verifying the final memory footprint. This flaw is classified under CWE-400 (Uncontrolled Resource Consumption).
An attacker with the ability to supply or modify a Scriban template can exploit this behavior by constructing an exponential string growth payload. Upon evaluation, the .NET runtime will attempt to allocate continuous memory for the expanding string objects until the process exhausts all available heap memory. This results in an uncatchable OutOfMemoryException, causing the host application process to terminate abruptly and creating a severe Denial of Service condition.
The root cause of the vulnerability is the absence of secure-by-default resource limits within the Scriban TemplateContext and ParserOptions classes. Scriban exposes several configuration properties designed to prevent runaway execution, notably LimitToString, ExpressionDepthLimit, and ObjectRecursionLimit. However, in vulnerable versions, these properties initialize to values that impose no practical restrictions.
The LimitToString property dictates the maximum character count permitted for a string generated during template evaluation. By default, this property is set to 0, which the engine logic interprets as an unlimited length ceiling. Consequently, string operations are bounded only by the host operating system's available memory and the .NET runtime's internal string length limits.
Furthermore, .NET strings are immutable. Every concatenation operation creates a new string object in memory. When a string exceeds 85,000 bytes, the runtime allocates it on the Large Object Heap (LOH). Rapidly creating increasingly large string objects on the LOH causes severe memory fragmentation and forces frequent, expensive Garbage Collection (GC) cycles. The CPU overhead of the GC combined with the memory exhaustion accelerates the application crash.
The remediation effort introduced in commit a6fe6074199e5c04f4d29dc8d8e652b24d33e3e4 targets the default configuration values within the engine's core parsing and execution contexts. The patch modifies the constructors for ParserOptions and TemplateContext to establish baseline safety constraints.
// src/Scriban/Parsing/ParserOptions.cs - Patched
public ParserOptions()
{
ExpressionDepthLimit = 250; // Previously null
}The modification to ParserOptions successfully mitigates StackOverflow vectors during the AST generation phase by capping the maximum nesting depth of parsed expressions. Similarly, changes to TemplateContext introduce an ObjectRecursionLimit of 20, preventing memory exhaustion when rendering deep or circular object graphs.
However, analysis of the patched TemplateContext.cs reveals a critical residual risk. The LimitToString property remains initialized to 0.
// src/Scriban/TemplateContext.cs - Patched
public TemplateContext(ScriptObject builtin, IEqualityComparer<string> keyComparer)
{
// ...
LimitToString = 0; // Remains 0 (unlimited)
ObjectRecursionLimit = 20;
// ...
}Because LimitToString remains unbounded by default, the core exponential string growth vector is still viable unless the developer explicitly overrides this property during context instantiation. The patch addresses secondary exhaustion vectors but requires manual intervention to secure the primary string allocation vulnerability.
Exploitation requires the attacker to supply a template that executes an iterative string concatenation sequence. The default LoopLimit in Scriban is set to 1,000. An attacker only needs a fraction of this limit to exhaust process memory due to the nature of exponential growth.
The following proof-of-concept template demonstrates the attack vector:
{{ a = "a" }}
{{ for i in 1..30 }}
{{ a = a + a }}
{{ end }}The script initializes a variable a with a single character. The subsequent for loop executes 30 iterations. In each iteration, the variable a is concatenated with itself, doubling its length. The mathematical growth curve is $O(2^n)$.
After 10 iterations, the string length is 1,024 bytes. After 20 iterations, it reaches 1,048,576 bytes (~1MB). At the 30th iteration, the string length attempts to reach 1,073,741,824 bytes (~1GB). The memory allocation requests scale so rapidly that the host application will crash with an OutOfMemoryException long before reaching the 1,000-iteration default loop limit.
The impact of this vulnerability is limited strictly to Availability. Exploitation does not permit remote code execution, nor does it provide the attacker with access to unauthorized data. However, the resulting Denial of Service is absolute and requires zero authentication if the application exposes template rendering to anonymous users.
When the .NET runtime encounters an OOM condition caused by heap exhaustion, it terminates the host process. In modern microservice architectures, an orchestration platform (like Kubernetes) will detect the crashed container and attempt to restart it. If the attacker automates the payload delivery, they can create a continuous crash-loop condition, permanently disabling the targeted service.
Applications that evaluate templates on background worker threads are particularly at risk. An unhandled OutOfMemoryException on a background thread will tear down the entire application domain, impacting all active user sessions and terminating in-flight transactions. The CVSS vector for this vulnerability reflects a High severity score due to the low complexity of the attack and the severe impact on system availability.
The primary remediation step is to update the Scriban NuGet package to version 5.12.1, 6.5.7, or later. These versions include the default limits for expression depth and object recursion. However, upgrading the package alone is insufficient to fully protect against the string growth vector.
Developers must explicitly enforce safe resource limits when instantiating the TemplateContext object. Setting a strict upper bound on string allocation ensures the engine halts execution before memory exhaustion occurs.
var context = new TemplateContext();
// Restrict string generation to a maximum of 1MB
context.LimitToString = 1048576;
// Restrict loop iterations to a safe threshold
context.LoopLimit = 100;
// Ensure recursive limit is maintained
context.ObjectRecursionLimit = 20;In scenarios where arbitrary users supply templates, input validation is a necessary defense-in-depth measure. Applications should parse the submitted template into an AST and inspect it for iterative concatenation patterns before passing it to the evaluation engine. Any template containing loop constructs that modify variables used in their own condition or body should be flagged and rejected.
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 Scriban | < 5.12.1 | 5.12.1 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-400 |
| Attack Vector | Network |
| CVSS v3.1 Score | 7.5 |
| Impact | Denial of Service (DoS) |
| Exploit Status | Proof of Concept Available |
| Authentication Required | None |
The software does not properly control the allocation and maintenance of a limited resource thereby enabling an actor to influence the amount of resources consumed, eventually leading to the exhaustion of available resources.
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.