Skip to content

Commit 62d6a03

Browse files
1 parent 288c551 commit 62d6a03

File tree

1 file changed

+55
-0
lines changed

1 file changed

+55
-0
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-x6m9-38vm-2xhf",
4+
"modified": "2026-03-24T22:09:49Z",
5+
"published": "2026-03-24T22:09:49Z",
6+
"aliases": [],
7+
"summary": "Scriban has an authorization bypass due to stale include cache surviving TemplateContext.Reset() ",
8+
"details": "## Summary\n\n`TemplateContext.Reset()` claims that a `TemplateContext` can be reused safely on the same thread, but it does not clear `CachedTemplates`. If an application pools `TemplateContext` objects and uses an `ITemplateLoader` that resolves content per request, tenant, or user, a previously authorized include can be served to later renders without calling `TemplateLoader.Load()` again.\n\n## Details\n\nThe relevant code path is:\n\n- `TemplateContext.Reset()` only clears output, globals, cultures, and source files in `src/Scriban/TemplateContext.cs` lines 877–902.\n- `CachedTemplates` is initialized once and kept on the context in `src/Scriban/TemplateContext.cs` line 197.\n- `include` resolves templates through `IncludeFunction.Invoke()` in `src/Scriban/Functions/IncludeFunction.cs` lines 29–43.\n- `IncludeFunction.Invoke()` calls `TemplateContext.GetOrCreateTemplate()` in `src/Scriban/TemplateContext.cs` lines 1249–1256.\n- If a template path is already present in `CachedTemplates`, Scriban returns the cached compiled template and does **not** call `TemplateLoader.Load()` again.\n\nThis becomes a security issue when `ITemplateLoader.Load()` returns request-dependent content. A first render can prime the cache with an admin-only or tenant-specific template, and later renders on the same reused `TemplateContext` will receive that stale template even after `Reset()`.\n\n---\n\n## Proof of Concept\n\n### Setup\n\n```bash\nmkdir scriban-poc1\ncd scriban-poc1\ndotnet new console --framework net8.0\ndotnet add package Scriban --version 6.6.0\n```\n\n### `Program.cs`\n\n```csharp\nusing Scriban;\nusing Scriban.Parsing;\nusing Scriban.Runtime;\n\nvar loader = new SwitchingLoader();\nvar context = new TemplateContext\n{\n TemplateLoader = loader,\n};\n\nvar template = Template.Parse(\"{{ include 'profile' }}\");\n\nloader.Content = \"admin-only\";\nConsole.WriteLine(\"first=\" + template.Render(context));\n\ncontext.Reset();\n\nloader.Content = \"guest-view\";\nConsole.WriteLine(\"second=\" + template.Render(context));\n\nsealed class SwitchingLoader : ITemplateLoader\n{\n public string Content { get; set; } = string.Empty;\n\n public string GetPath(TemplateContext context, SourceSpan callerSpan, string templateName) => templateName;\n\n public string Load(TemplateContext context, SourceSpan callerSpan, string templatePath) => Content;\n\n public ValueTask<string> LoadAsync(TemplateContext context, SourceSpan callerSpan, string templatePath)\n => new(Content);\n}\n```\n\n### Run\n\n```bash\ndotnet run\n```\n\n### Actual Output\n\n```\nfirst=admin-only\nsecond=admin-only\n```\n\n### Expected Output\n\n```\nfirst=admin-only\nsecond=guest-view\n```\n\nThe second render should reload the template after `Reset()`, but it instead reuses the cached compiled template from the previous render.\n\n---\n\n## Impact\n\nThis is a cross-render data isolation issue. Any application that reuses `TemplateContext` objects and uses a request-dependent `ITemplateLoader` can leak previously authorized template content across requests, users, or tenants.\n\nThe issue impacts applications that:\n\n- Pool or reuse `TemplateContext`\n- Call `Reset()` between requests\n- Use `include`\n- Resolve include content based on request-specific state",
9+
"severity": [
10+
{
11+
"type": "CVSS_V3",
12+
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N"
13+
}
14+
],
15+
"affected": [
16+
{
17+
"package": {
18+
"ecosystem": "NuGet",
19+
"name": "scriban"
20+
},
21+
"ranges": [
22+
{
23+
"type": "ECOSYSTEM",
24+
"events": [
25+
{
26+
"introduced": "0"
27+
},
28+
{
29+
"fixed": "7.0.0"
30+
}
31+
]
32+
}
33+
]
34+
}
35+
],
36+
"references": [
37+
{
38+
"type": "WEB",
39+
"url": "https://github.com/scriban/scriban/security/advisories/GHSA-x6m9-38vm-2xhf"
40+
},
41+
{
42+
"type": "PACKAGE",
43+
"url": "https://github.com/scriban/scriban"
44+
}
45+
],
46+
"database_specific": {
47+
"cwe_ids": [
48+
"CWE-226"
49+
],
50+
"severity": "HIGH",
51+
"github_reviewed": true,
52+
"github_reviewed_at": "2026-03-24T22:09:49Z",
53+
"nvd_published_at": null
54+
}
55+
}

0 commit comments

Comments
 (0)