Skip to main content

LiquidJS EUVDEUVD-2026-28886

| CVE-2026-41311 HIGH
Uncontrolled Recursion (CWE-674)
2026-04-24 https://github.com/harttle/liquidjs GHSA-4rc3-7j7w-m548
7.5
CVSS 3.1 · GitHub Advisory
Share

Severity by source

GitHub Advisory PRIMARY
7.5 HIGH
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

Primary rating from GitHub Advisory · only source for this CVE.

CVSS VectorGitHub Advisory

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
Confidentiality
None
Integrity
None
Availability
High

Lifecycle Timeline

4
Analysis Generated
Apr 24, 2026 - 16:16 vuln.today
Analysis Generated
Apr 24, 2026 - 16:00 vuln.today
Patch released
Apr 24, 2026 - 16:00 nvd
Patch available
CVE Published
Apr 24, 2026 - 15:34 nvd
HIGH 7.5

Blast Radius

ecosystem impact
† from your stack dependencies † transitive graph · vuln.today resolves 4-path depth
  • 22 npm packages depend on liquidjs (11 direct, 11 indirect)

Ecosystem-wide dependent count for version 10.25.7.

DescriptionGitHub Advisory

Summary

A circular block reference in {% layout %} / {% block %} causes an infinite recursive loop, consuming all available memory (~4GB) and crashing the Node.js process with FATAL ERROR: JavaScript heap out of memory. This allows any user who can submit a Liquid template to perform a Denial of Service attack.

Details

In src/tags/block.ts, during OUTPUT mode, each block looks up its render function from ctx.getRegister('blocks')[this.block]. When a block with name a is nested inside another block also named a in a child template, the inner block finds the outer block's render function and calls it. The outer block's templates contain the inner block again, creating infinite recursion with no termination condition.

Relevant code (src/tags/block.ts, getBlockRender method):

typescript
private getBlockRender (ctx: Context) {
  const { liquid, templates } = this
  const renderChild = ctx.getRegister('blocks')[this.block]
  const renderCurrent = function * (superBlock: BlockDrop, emitter: Emitter) {
    ctx.push({ block: superBlock })
    yield liquid.renderer.renderTemplates(templates, ctx, emitter)
    ctx.pop()
  }
  return renderChild
    ? (superBlock: BlockDrop, emitter: Emitter) => renderChild(
        new BlockDrop(
          (emitter: Emitter) => renderCurrent(superBlock, emitter)
        ),
        emitter)
    : renderCurrent
}

When renderChild exists (same-name block found), it calls renderChild which re-renders templates containing the nested block, which again finds renderChild, and so on - infinite loop.

PoC

1. Create a layout file (layout.html):

liquid
<header>{% block a %}default-a{% endblock %}</header>
<main>{% block b %}default-b{% endblock %}</main>
<footer>{% block c %}default-c{% endblock %}</footer>

2. Create a template that uses the layout:

liquid
{% layout "layout" %}
{% block a %}outer-a {% block a %}inner-a{% endblock %}{% endblock %}
{% block b %}content-b{% endblock %}
{% block c %}content-c{% endblock %}

3. Render:

javascript
const { Liquid } = require('liquidjs')
const liquid = new Liquid({ root: './', extname: '.html' })
liquid.renderFile('template').then(console.log)
// Result: process hangs, memory grows to ~4GB, then crashes with OOM

The anonymous block variant also triggers the same issue:

liquid
{% layout "parent" %}
{%block%}A{%block%}B{%endblock%}{%endblock%}

Impact

Denial of Service (DoS). Any application that accepts user-provided or user-influenced Liquid templates - such as CMS platforms, email template builders, multi-tenant SaaS products, or static site generators with untrusted input - can be crashed by a single malicious template. The attack requires no authentication beyond the ability to submit a template, and no special configuration. The Node.js process is killed by the OS due to memory exhaustion, causing complete service disruption.

AnalysisAI

Infinite recursion in LiquidJS template engine crashes Node.js processes via out-of-memory condition when attackers submit templates with circular block references. Unauthenticated remote attackers can consume ~4GB RAM and terminate any application accepting user-provided Liquid templates by nesting identically-named blocks within {% layout %} / {% block %} tags. Vendor patch available via GitHub commit e2311df. CVSS 7.5 (High) reflects network-accessible, low-complexity attack requiring no privileges or user interaction, causing complete availability loss.

Technical ContextAI

LiquidJS is a JavaScript implementation of the Liquid template language for Node.js applications, commonly used in CMS platforms, email builders, static site generators, and multi-tenant SaaS products. The vulnerability resides in src/tags/block.ts where the getBlockRender method processes template inheritance. During OUTPUT mode, blocks retrieve their render functions from ctx.getRegister('blocks')[this.block]. When a child template defines a block with name 'a' nested inside another block also named 'a', the inner block's lookup retrieves the outer block's render function, which re-renders templates containing the inner block, creating unbounded recursion. This matches CWE-674 (Uncontrolled Recursion) where the code lacks termination conditions for self-referential template structures. The npm package identifier is pkg:npm/liquidjs, affecting applications that parse untrusted or user-influenced Liquid markup without input validation on block nesting patterns.

RemediationAI

Immediately upgrade LiquidJS to the patched version containing commit e2311dfd6e82f73509308aa8a3a1fafc92e226f0 available from the official GitHub repository (https://github.com/harttle/liquidjs/commit/e2311dfd6e82f73509308aa8a3a1fafc92e226f0). Consult the GitHub security advisory GHSA-4rc3-7j7w-m548 for the specific release version number. If immediate patching is not feasible, implement template input validation to block nested blocks with identical names by parsing templates before rendering and rejecting structures where {% block X %} appears within another {% block X %}. Alternatively, enforce resource limits using Node.js --max-old-space-size flag (e.g., 512MB) combined with process monitoring to restart crashed instances, though this only mitigates impact and does not prevent the attack. For high-risk environments, disable user-submitted templates entirely or switch to a sandboxed template rendering service with isolated memory spaces per render operation. Note that memory limits will cause faster crashes but still result in service disruption; validation or patching are the only complete mitigations. Review application logs for abnormal memory growth patterns or OOM crashes as potential exploitation indicators.

CVE-2024-55591 CRITICAL POC
9.8 Jan 14

FortiOS and FortiProxy contain an authentication bypass via the Node.js websocket module allowing unauthenticated remote

CVE-2014-7205 CRITICAL POC
10.0 Oct 08

Eval injection vulnerability in the internals.batch function in lib/batch.js in the bassmaster plugin before 1.5.2 for t

CVE-2025-59528 CRITICAL POC
10.0 Sep 22

Flowise version 3.0.5 contains a remote code execution vulnerability in the CustomMCP node. The mcpServerConfig paramete

CVE-2017-14849 HIGH POC
7.5 Sep 28

Node.js 8.5.0 before 8.6.0 allows remote attackers to access unintended files, because a change to ".." handling was inc

CVE-2017-5941 CRITICAL POC
9.8 Feb 09

An issue was discovered in the node-serialize package 0.0.4 for Node.js. Rated critical severity (CVSS 9.8), this vulner

CVE-2014-3744 HIGH POC
7.5 Oct 23

Directory traversal vulnerability in the st module before 0.2.5 for Node.js allows remote attackers to read arbitrary fi

CVE-2014-9566 HIGH POC
7.5 Mar 10

Multiple SQL injection vulnerabilities in the Manage Accounts page in the AccountManagement.asmx service in the Solarwin

CVE-2013-4660 MEDIUM POC
6.8 Jun 28

The JS-YAML module before 2.0.5 for Node.js parses input without properly considering the unsafe !!js/function tag, whic

CVE-2015-5688 MEDIUM POC
5.0 Sep 04

Directory traversal vulnerability in lib/app/index.js in Geddy before 13.0.8 for Node.js allows remote attackers to read

CVE-2026-45321 CRITICAL POC
9.6 May 12

Credential-harvesting malware compromised 84 versions of 42 TanStack npm packages on 2026-05-11 via chained GitHub Actio

CVE-2014-7192 CRITICAL POC
10.0 Dec 11

Eval injection vulnerability in index.js in the syntax-error package before 1.1.1 for Node.js 0.10.x, as used in IBM Rat

CVE-2013-4450 MEDIUM POC
5.0 Oct 21

The HTTP server in Node.js 0.10.x before 0.10.21 and 0.8.x before 0.8.26 allows remote attackers to cause a denial of se

Share

EUVD-2026-28886 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy