LiquidJS Memory Limit Bypass Leads to Denial of Service
A vulnerability in LiquidJS versions 10.24.0 and earlier allows a threat actor with control over template content to bypass the `memoryLimit` protection mechanism, leading to a denial of service by using reverse range expressions to allocate unlimited memory and a string flattening operation to cause a V8 Fatal error that crashes the Node.js process.
A critical vulnerability exists in LiquidJS versions 10.24.0 and earlier, allowing attackers with control over Liquid template content to bypass the memoryLimit security feature. This bypass is achieved by exploiting reverse range expressions (e.g., (100000000..1)) within the template, which causes the internal memory counter to become negative. Subsequently, attackers can construct large strings using the append filter, creating a cons-string. When a filter requiring string flattening, such as replace, is applied, V8 attempts to allocate a large contiguous memory block, triggering a fatal error that crashes the Node.js process. This vulnerability enables a single HTTP request to cause a service-wide denial of service.
Attack Chain
- The attacker crafts a Liquid template containing reverse range expressions, such as
{% for x in (100000000..1) %}{% endfor %}. - These expressions are evaluated by LiquidJS, leading to a negative value being passed to the
memoryLimit.use()function. - The
Limiter.use()function incorrectly updates the internal memory counter, allowing it to go negative. - The attacker then uses the
appendfilter to create a large cons-string (e.g.,{% assign s = s | append: s %}repeated 27 times). - This cons-string is logically large (e.g., 134MB) but consumes minimal actual memory.
- The attacker uses a filter like
replacethat requires flattening the cons-string into a contiguous memory buffer. - V8 attempts to allocate a large memory block to flatten the string, exceeding available resources.
- This triggers a V8 Fatal error, causing the Node.js process to crash and resulting in a denial of service.
Impact
Successful exploitation of this vulnerability allows an attacker to crash the Node.js process running LiquidJS, leading to a service-wide denial of service. This impacts applications using LiquidJS for templating, especially those that allow user-supplied templates, such as CMS systems, email template editors, and SaaS platforms. A single malicious HTTP request can terminate the entire Node.js process, requiring manual intervention or container restart policies to recover. This issue affects LiquidJS version 10.24.0 and earlier.
Recommendation
- Apply appropriate input validation and sanitization to any user-provided Liquid templates to prevent the use of reverse ranges.
- Monitor web server logs for POST requests containing Liquid template syntax, especially those including reverse range expressions or excessive
appendfilter usage, to detect potential exploitation attempts. - Consider deploying the Sigma rule
Detect LiquidJS Template Injectionto identify requests with potentially malicious LiquidJS code. - Upgrade to a patched version of LiquidJS that addresses this vulnerability, when available.
Detection coverage 2
Detect LiquidJS Template Injection
mediumDetects HTTP requests containing LiquidJS template syntax, indicative of potential template injection attacks.
Detect LiquidJS Reverse Range Exploitation
highDetects HTTP requests that potentially exploit the LiquidJS memory limit bypass using reverse ranges.
Detection queries are available on the platform. Get full rules →