CVE-2026-33287
High · 7.5CVSS
7.5
EPSS
0.5%
Published
Mar 26, 2026
CISA due date
—
Cloudanix analysis
A small malicious template can make affected applications consume huge amounts of memory and crash, causing an outage.
- Exploitation
- Remote Unauthenticated
- Attacker needs
- None
- Complexity
- Low
- Impact
- Denial Of Service
- Component
- Library
- Class
- Denial of service
- Remediation
- Upgrade
- Effort
- Medium
- Patch risk
- Low
What it actually does
LiquidJS versions prior to 10.25.1 can under-account memory consumption in the `replace_first` filter. The implementation relies on JavaScript `String.prototype.replace()`, where replacement tokens such as `$&` expand to the matched substring. Because LiquidJS charges the configured `memoryLimit` against the original input length rather than the post-replacement output size, a crafted template or template-controlled input can cause extreme output amplification while appearing to remain within the intended memory budget. The result is resource exhaustion, typically Node.js heap growth, garbage-collection pressure, process termination, or service unavailability. The flaw is remotely exploitable when an application renders attacker-controlled Liquid templates or attacker-controlled values that reach vulnerable `replace_first` usage.
Why it matters to the business
Applications that allow user-supplied Liquid templates, themes, content blocks, emails, pages, or other rendered markup may be crashed by a small malicious input, causing denial of service for affected web, publishing, notification, or rendering workflows. The CVSS score indicates high availability impact, but the current EPSS score is low and it is not listed in CISA KEV, suggesting no broad confirmed exploitation at this time. Organizations with public-facing template rendering or large downstream dependency exposure should still prioritize remediation because exploitation requires no authentication or user interaction if untrusted rendering is exposed.
How an attack unfolds
An attacker first identifies an application path that renders LiquidJS templates or processes attacker-controlled Liquid content. They then craft input using the vulnerable `replace_first` behavior and JavaScript replacement semantics, especially `$&`, so that each replacement reproduces or multiplies the matched content. Because the vulnerable LiquidJS memory accounting only considers the input size, the payload can stay under the configured `memoryLimit` while producing a much larger rendered output. Repeated or nested use can create exponential memory amplification, potentially reaching very large expansion ratios. When processed by the Node.js service, memory usage spikes, garbage collection becomes ineffective, and the process may become unresponsive or crash with an out-of-memory condition, producing a denial of service.
How to fix it
Upgrade LiquidJS to version 10.25.1 or later wherever it is used directly or transitively. If immediate upgrade is not possible, reduce exposure by disabling or restricting user-supplied Liquid template rendering, blocking untrusted use of `replace_first`, validating or sanitizing replacement strings that contain JavaScript replacement tokens such as `$&`, and enforcing independent output-size, render-time, request-rate, and process-memory limits outside LiquidJS. For public-facing rendering endpoints, apply rate limiting and isolate template rendering in a constrained worker process or container so crashes do not take down the primary application. Rebuild and redeploy affected services after updating dependency lockfiles, and verify that runtime artifacts no longer include vulnerable LiquidJS versions prior to 10.25.1.
How to confirm the fix worked
Confirm dependency versions with package manager tooling such as `npm ls liquidjs`, `yarn why liquidjs`, `pnpm why liquidjs`, and by inspecting lockfiles for `liquidjs` entries. The installed version should be 10.25.1 or later. Validate running artifacts, not only source repositories, by checking deployed package manifests, container images, serverless bundles, and build outputs. Exercise template-rendering paths with benign regression tests that use `replace_first` and replacement-token syntax to confirm rendering succeeds without abnormal memory growth. Monitor during validation for Node.js heap spikes, process restarts, HTTP 5xx increases, render timeouts, and out-of-memory logs. If a compensating control is used, confirm that output-size limits, render timeouts, and worker isolation actually terminate oversized renders without impacting the main service.
Typical attack path
- Find an externally reachable feature that renders LiquidJS content, such as custom pages, themes, templates, previews, notifications, or CMS-like content.
- Submit or store a crafted Liquid template or variable value using `replace_first` with replacement tokens such as `$&`.
- Trigger rendering of the malicious content, either directly through a request or indirectly through a preview, publish, email, or batch rendering workflow.
- Cause LiquidJS to generate output far larger than the accounted input size, bypassing the intended `memoryLimit` control.
- Exhaust Node.js heap or available process memory, leading to high CPU from garbage collection, request timeouts, process crashes, container restarts, or service outage.
- Repeat requests or use stored malicious content to keep the service unstable until the vulnerable package is patched or the payload is removed.
How to detect it
Look for evidence of denial-of-service activity against LiquidJS rendering paths. Useful sources include application logs, reverse-proxy and WAF logs, Node.js process logs, container or orchestrator restart events, process supervisor logs, APM traces, and stored user-generated templates or content. Focus on repeated requests or stored content containing Liquid filter syntax, especially `replace_first` combined with `$&`, followed by memory growth, long render times, HTTP 500/502/503/504 responses, process exits, or container restarts. In Node.js logs, search for heap exhaustion messages such as `JavaScript heap out of memory`, `Reached heap limit`, and allocation failures. In proxy logs, correlate suspicious template submissions or preview/render requests with spikes in response latency, upstream resets, and repeated failures from the same source. If the application stores templates, inspect recently created or modified template content for unusually repetitive `replace_first` usage or replacement strings containing `$&`. Absence of these indicators does not prove non-exploitation, because a successful denial-of-service attempt may leave only generic crash or restart telemetry.
- replace_first
- $&
- replace_first: "$&"
- replace_first: '$&'
- JavaScript heap out of memory
- FATAL ERROR: Reached heap limit Allocation failed
- FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed
- Allocation failed - JavaScript heap out of memory
- CALL_AND_RETRY_LAST Allocation failed
- heap out of memory
- Mark-sweep
- Mark-compact
- Container killed due to memory usage
- OOMKilled
- exit code 137
- upstream prematurely closed connection
- upstream timed out
- HTTP 503
- HTTP 504
What your security team should do
- Inventory all applications and services that include LiquidJS, especially those exposing user-controlled templates, themes, CMS content, emails, previews, or markdown/static-site rendering.
- Prioritize upgrade to LiquidJS 10.25.1 or later for internet-facing or multi-tenant rendering services, even though the vulnerability is not currently in CISA KEV and has low EPSS.
- Search source and templates for use of `replace_first` combined with attacker-controlled content or replacement strings containing `$&` or similar replacement-token syntax.
- Add defense-in-depth controls: output-size caps, render timeouts, request rate limits, memory-constrained rendering workers, and crash isolation for template processing.
- Review logs from the publication date onward for abnormal Node.js memory errors, renderer crashes, repeated template-rendering failures, and suspicious requests containing Liquid filter syntax.
- Create SIEM detections for Node.js out-of-memory messages correlated with template rendering endpoints or requests containing `replace_first` and `$&`.
- If exploitation is suspected, preserve application logs, reverse-proxy logs, process supervisor logs, container restart history, and any stored user-created templates or content for forensic review.
The record
LiquidJS is a Shopify / GitHub Pages compatible template engine in pure JavaScript. Prior to version 10.25.1, the `replace_first` filter in LiquidJS uses JavaScript's `String.prototype.replace()` which interprets `$&` as a back reference to the matched substring. The filter only charges `memoryLimit` for the input string length, not the amplified output. An attacker can achieve exponential memory amplification (up to 625,000:1) while staying within the `memoryLimit` budget, leading to denial of service. Version 10.25.1 patches the issue.
Affected packages
| Ecosystem | Package | Introduced | Fixed |
|---|---|---|---|
| npm | liquidjs | 0 | No fix |
Related vulnerabilities
- GHSA-6q5m-63h6-5x4v LiquidJS has Exponential Memory Amplification through its replace_first Filter $& Pattern Same vulnerability
- CVE-2026-45617 LiquidJS is a Shopify/GitHub Pages compatible template engine written in pure JavaScript. Also affects liquidjs
- CVE-2026-45357 LiquidJS is a Shopify/GitHub Pages compatible template engine written in pure JavaScript. Also affects liquidjs
- CVE-2026-44645 LiquidJS is a Shopify/GitHub Pages compatible template engine written in pure JavaScript. Also affects liquidjs
- CVE-2026-44646 LiquidJS is a Shopify/GitHub Pages compatible template engine written in pure JavaScript. Also affects liquidjs
- CVE-2026-44644 LiquidJS is a Shopify/GitHub Pages compatible template engine written in pure JavaScript. Also affects liquidjs
- GHSA-gf2q-c269-pqgc LiquidJS is Vulnerable to Remote Code Execution Also affects liquidjs
- GHSA-r7g9-xpmj-5fcq LiquidJS Vulnerable to ReDoS via Quadratic Backtracking in `strip_html` Filter Regex Also affects liquidjs