Mar 25, 2026·7 min read·38 visits
Scriban versions before 7.0.0 are vulnerable to Denial of Service via unbounded resource consumption. Unauthenticated or low-privileged users can crash the host application by providing crafted template expressions that bypass configured string length and loop limits.
The Scriban .NET templating engine versions prior to 7.0.0 contain three distinct denial-of-service vulnerabilities. These flaws arise from improper enforcement of resource limits during expression evaluation, specifically concerning string multiplication, bitwise shifts, and range enumerations. An attacker with template authoring privileges can exploit these vectors to trigger OutOfMemoryException or CPU exhaustion, resulting in abrupt application termination or degraded performance.
Scriban is a fast, powerful, and safe templating language and engine for .NET, frequently utilized in content management systems, static site generators, and email marketing platforms. The engine exposes a configuration object, TemplateContext, which administrators use to enforce execution limits. These boundaries include LimitToString for string allocations and LoopLimit for maximum iteration counts.
Versions of Scriban prior to 7.0.0 fail to enforce these safety controls across three specific expression evaluation paths. The application trusts the constraints established in TemplateContext but contains implementation flaws that allow certain operations to bypass these checks entirely. This results in unrestricted resource allocation and processing.
An attacker who can supply or modify template content can exploit these paths to cause a Denial of Service (DoS). The vulnerabilities are classified under CWE-400 (Uncontrolled Resource Consumption), CWE-770 (Allocation of Resources Without Limits or Throttling), and CWE-834 (Excessive Iteration). The impact varies depending on the targeted vector but culminates in either process termination or complete thread pool exhaustion.
The attack vector requires no elevated privileges beyond the ability to submit template data. Applications that parse user-provided strings via Template.Parse() without pre-processing validation are inherently vulnerable. The severity is constrained to a 6.5 Medium rating due to the requirement of application-specific template input mechanisms and the lack of confidentiality or integrity impacts.
The first vulnerability vector exists within ScriptBinaryExpression.cs handling the string multiplication operator (string * int). The CalculateToString method attempts to replicate the input string a specified number of times using a standard for loop and a StringBuilder. The implementation lacks a pre-allocation check against context.LimitToString, allowing the StringBuilder to grow until the .NET runtime throws an OutOfMemoryException.
The second vector involves the ShiftLeft operator (<<), implemented in CalculateLongWithInt and CalculateBigIntegerNoFit. Unlike the exponentiation operator (Power), which uses BigInteger.ModPow and enforces a MaxBigInteger boundary, the left-shift operation applies no such limits. Shifting a BigInteger by an extremely large integer value forces the .NET runtime to allocate a backing array large enough to hold the shifted bits, again leading to an immediate OutOfMemoryException.
The third vector exploits range operators (.. and ..<) used in conjunction with built-in array functions. Range operators in Scriban return lazy IEnumerable<object> iterators. When these ranges are passed directly to functions like array.size or array.join, the underlying implementation fully enumerates the iterator. Because this enumeration happens inside the native function rather than the template engine's main execution loop, it never invokes context.StepLoop(). Consequently, the enumeration entirely bypasses the context.LoopLimit protection, causing CPU exhaustion.
The flaw in the string multiplication implementation is located between lines 319 and 334 in src/Scriban/Syntax/Expressions/ScriptBinaryExpression.cs. The vulnerable code executes a loop based strictly on user-supplied values without boundary verification.
var leftText = context.ObjectToString(left);
var builder = new StringBuilder();
for (int i = 0; i < value; i++)
{
builder.Append(leftText);
}
return builder.ToString();The fundamental issue here is that context.LimitToString (which defaults to 1MB) is ignored. The patch resolves this by introducing a mathematical boundary check prior to the loop execution. By calculating the expected final size (long)value * leftText.Length, the engine can throw a controlled ScriptRuntimeException before any substantial memory allocation occurs.
// Patched logic
if (context.LimitToString > 0 && (long)value * leftText.Length > context.LimitToString)
{
throw new ScriptRuntimeException(span, "String multiplication would exceed LimitToString");
}The fix for the loop limit bypass requires the engine to track iteration counts within the built-in functions that consume IEnumerable<object>. The patched RangeInclude and RangeExclude structures are updated to increment and verify against context.LoopLimit during every iteration step. This ensures that a range calculation like (0..1000000000) halts after reaching the threshold.
Exploitation relies on passing a single crafted expression into the Template.Parse() method and subsequently calling template.Render(context). The attacker does not need to understand the underlying architecture, only that Scriban is processing the input.
To trigger the string multiplication Out of Memory (OOM) condition, the attacker supplies a template that multiplies a small string by an exceptionally large integer. The code below demonstrates this attack. The default LimitToString configuration of 1,048,576 bytes fails to prevent the approximately 2GB allocation attempt.
var template = Template.Parse("{{ 'AAAA' * 500000000 }}");
var context = new TemplateContext();
template.Render(context); // Throws OutOfMemoryExceptionFor the bitwise shift OOM, the attacker leverages the << operator. The resulting BigInteger allocation bypasses normal numerical limits. The following snippet forces the application to allocate a BigInteger containing 100 million bits (approximately 12.5MB per evaluation, easily scaled by the attacker to exhaust available memory).
var template = Template.Parse("{{ 1 << 100000000 }}");
var context = new TemplateContext();
template.Render(context); // Throws OutOfMemoryExceptionThe CPU exhaustion vector targets the loop limit bypass. By piping an enormous range into the array.size built-in function, the application attempts to enumerate 1 billion items synchronously. This blocks the executing thread indefinitely, starving the application's thread pool and resulting in a denial of service.
var template = Template.Parse("{{ (0..1000000000) | array.size }}");
var context = new TemplateContext();
template.Render(context); // High CPU utilization, hangs executionThe primary consequence of this vulnerability is a complete Denial of Service. In the context of .NET runtime environments, an OutOfMemoryException is typically a fatal error. Modern .NET runtimes generally terminate the process entirely when an OOM exception is thrown by the execution engine, rather than allowing the application to catch and recover from the error.
Process termination affects all users currently interacting with the host application. If the application handles web requests, all active connections are dropped. In environments orchestrated by container managers (e.g., Kubernetes), this leads to continuous pod restarts (CrashLoopBackOff) if the attacker automates the malicious request.
The CPU exhaustion vector introduces a secondary impact model. While it may not crash the process immediately, it ties up application threads. If an attacker submits multiple requests utilizing the loop bypass vector, the .NET thread pool becomes starved. Subsequent legitimate requests will queue and eventually time out, effectively rendering the application unresponsive.
The definitive mitigation for this vulnerability is upgrading the Scriban NuGet package to version 7.0.0 or later. This release introduces comprehensive boundary checks in the abstract syntax tree evaluation logic, explicitly capping string operations, bitwise shifts, and range iterators to the limits defined in TemplateContext.
If immediate patching is not technically feasible, development teams must implement input validation workarounds. The most robust temporary measure involves restricting template authoring capabilities strictly to highly trusted administrators. In multi-tenant environments where user-supplied templates are a core feature, restricting access may not be an option.
In cases where untrusted input must be processed by vulnerable versions, implement a strict pre-compilation regex filter. The filter should scan the template string and reject inputs containing multiplication operators (*), left shift operators (<<), and range operators (.. and ..<). This degrades the functionality of the templating engine but neutralizes the known attack vectors.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
Scriban Alexandre Mutel | >= 0.1.0, < 7.0.0 | 7.0.0 |
| Attribute | Detail |
|---|---|
| Vulnerability Type | Denial of Service (DoS) |
| CWE ID | CWE-400, CWE-770, CWE-834 |
| CVSS v3.1 Score | 6.5 Medium |
| Attack Vector | Network (Remote) |
| Privileges Required | Low |
| User Interaction | None |
| Exploit Status | Proof of Concept available |
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.
CVE-2026-48861 is a client-side HTTP request-line CRLF (Carriage Return Line Feed) injection vulnerability in the popular Elixir HTTP client library, Mint. The vulnerability permits HTTP Request Splitting and HTTP Request Smuggling when an application forwards untrusted, attacker-controlled inputs to Mint's HTTP client requests as either the HTTP request method or target. By embedding CRLF characters within these parameters, an attacker can terminate the request line prematurely, inject malicious headers, or pipeline entirely independent requests. These smuggled requests are then processed by upstream or downstream proxy servers as separate HTTP queries on the same TCP connection. While Mint version 1.7.0 introduced target validation to secure the request target, the HTTP request method parameter remained completely unvalidated. This flaw allows attackers to bypass routing filters, access restricted internal APIs, or poison HTTP caches under default configurations.
An Inconsistent Interpretation of HTTP Requests (HTTP Request/Response Smuggling) vulnerability in the Elixir Mint HTTP client allows attacker-controlled HTTP/1 servers to desynchronize response framing on shared connections due to over-lenient parsing of sign-prefixed Content-Length headers.
An allocation of resources without limits or throttling vulnerability in Elixir Mint allows an attacker-controlled HTTP/2 server to exhaust memory in a Mint client. The vulnerability is exploited by sending a HEADERS frame without the END_HEADERS flag followed by an infinite stream of CONTINUATION frames. Because the client lacks limits on the incoming header-block accumulator, the client continuously consumes memory until an out-of-memory crash occurs.
CVE-2026-48596 is an Improper Neutralization of CRLF Sequences in HTTP Headers (HTTP Request/Response Splitting, CWE-113) in the Elixir Tesla HTTP client. The flaw resides in how multipart content-type parameters are joined and serialized, enabling attackers to inject arbitrary headers or split HTTP requests when applications pass untrusted inputs to the parameters of multipart uploads.
An improper handling of highly compressed data (decompression bomb) vulnerability exists in the Elixir Tesla HTTP client when utilizing response decompression middlewares. By serving highly compressed responses or stacked content-encoding headers, a malicious server can cause arbitrary heap exhaustion, leading to a denial of service (DoS) crash in the BEAM virtual machine.
A high-severity security vulnerability in Elixir's Tesla HTTP client library (CVE-2026-48595) allows unauthenticated remote attackers to harvest sensitive credentials, including Authorization headers and cookies. The flaw resides in the 'Tesla.Middleware.FollowRedirects' component, which performs case-sensitive lookups when stripping credentials during cross-origin redirects. Because HTTP headers are case-insensitive by RFC specifications, standard canonical casing (e.g., 'Authorization') bypasses the lowercase-only blocklist, leaking tokens to untrusted external redirect destinations.