Scriban has Multiple Denial-of-Service Vectors via Unbounded Resource Consumption During Expression Evaluation
Date: 2026-03
Affected: nuget/Scriban
Attack vector: dos
Category: vulnerability-disclosure
Severity: Medium
CWE: CWE-400
CVSS: 6.5 (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H)

## Summary Scriban's expression evaluation contains three distinct code paths that allow an attacker who can supply a template to cause denial of service through unbounded memory allocation or CPU exhaustion. The existing safety controls (`LimitToString`, `LoopLimit`) do not protect these paths, giving applications a false sense of safety when evaluating untrusted templates. ## Details ### Vector 1: Unbounded string multiplication In `ScriptBinaryExpression.cs`, the `CalculateToString` method handles the `string * int` operator by looping without any upper bound: ```csharp // src/Scriban/Syntax/Expressions/ScriptBinaryExpression.cs:319-334 var leftText = context.ObjectToString(left); var builder = new StringBuilder(); for (int i = 0; i < value; i++) { builder.Append(leftText); } return builder.ToString(); ``` The `LimitToString` safety control (default 1MB) does **not** protect this code path. It only applies to `ObjectToString` output conversions in `TemplateContext.Helpers.cs` (lines 101-121), not to intermediate string values constructed inside `CalculateToString`. The `LoopLimit` also does not apply because this is a C# `for` loop, not a template-level loop — `StepLoop()` is never called here. ### Vector 2: Unbounded BigInteger shift left The `CalculateLongWithInt` and `CalculateBigIntegerNoFit` methods handle `ShiftLeft` without any bound on the shift amount: ```csharp // src/Scriban/Syntax/Expressions/ScriptBinaryExpression.cs:710-711 case ScriptBinaryOpera


Mitigations:

Architectural layers (MAESTRO):