CSIRTS // UNIFIED SECURITY ADVISORY FEEDSYS ● ONLINE · POWERED BY INTELFUSIONS.COM

GHSA-8xx9-69p8-7jp3: LiquidJS has a renderLimit DoS guard bypass via empty `{% for %}` body

mediumCVSS 6.5CVE-2026-44645
Summary The renderLimit option — documented in docs/source/tutorials/dos.md as the mechanism that "mitigates this by limiting the time consumed by each render() call" — can be fully bypassed by a {% for %} (or {% tablerow %}) tag whose body is empty. The per-iteration time check is reached only when the body contains at least one template node, so a template like {%- for i in (1..N) -%}{%- endfor -%} iterates the full collection without ever consulting renderLimit. With a configured renderLimit of 50 ms, a single parseAndRenderSync call has been observed to consume 2.26 seconds (~45× over the limit) and scales linearly with N up to memoryLimit, allowing a low-privileged template author to wedge an event-loop thread for an attacker-chosen duration. Details Render.renderTemplates is the single point at which renderLimit is consulted: // src/render/render.ts 14: public * renderTemplates (templates: Template[], ctx: Context, emitter?: Emitter): IterableIterator<any> { 15: if (!emitter) { 16: emitter = ctx.opts.keepOutputType ? new KeepingTypeEmitter() : new SimpleEmitter() 17: } 18: const errors = [] 19: for (const tpl of templates) { 20: ctx.renderLimit.check(getPerformance().now()) 21: try { 22: const html = yield tpl.render(ctx, emitter) ... 32: } The check at line 20 lives inside the for (const tpl of templates) body. When templates.length === 0, the loop body never executes, so the limiter is never consulted on that invocation. The for tag re-enters renderTemplates once per collection item with no independent time check: // src/tags/for.ts 70: for (const item of collection) { 71: scope[this.variable] = item 72: ctx.continueCalled = ctx.breakCalled = false 73: yield r.renderTemplates(this.templates, ctx, emitter) 74: if (ctx.breakCalled) break 75: scope.forloop.next() 76: } When {%- for i in (1..N) -%}{%- endfor -%} is parsed, this.templates is []. Each of the N calls to r.renderTemplates(this.templates, ctx, emitter) therefore performs zero renderLimit.chec

Details

Source
GitHub Security Advisories (INTL · database · site)
Severity
medium — CVSS 6.5
Published
2026-05-27
Last updated
2026-07-09
Exploitation
Not in CISA KEV at last sync

Original advisory: https://github.com/advisories/GHSA-8xx9-69p8-7jp3

Exploitation outlook

EPSS (FIRST.org) estimates each CVE’s probability of exploitation in the next 30 days — here is the CSIRTS.com read on those numbers.

Referenced CVEs

CVECSIRTS overviewExternal
CVE-2026-44645coverage & exploitation statusNVD · CVE.org

More from GitHub Security Advisories