Cloudanix VulnDB

CVE-2026-45617

High · 7.5

CVSS

7.5

EPSS

0.7%

Published

Jun 17, 2026

CISA due date

—

Cloudanix analysis

Next patch cycle SSVC: Track

A flaw in a web template library can let someone slow down or knock offline affected services by sending specially crafted text.

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 10.25.7 and earlier contain a regular expression denial-of-service flaw in the built-in strip_html filter. Crafted input with many unterminated HTML opener tokens such as <script, <style, or <!-- triggers quadratic backtracking in the V8 JavaScript regex engine. Because Node.js executes this work on the main event loop, one request can block request processing for multiple seconds, and larger inputs increase CPU time nonlinearly. The LiquidJS memoryLimit setting does not effectively mitigate this condition because the vulnerable regex can consume unbounded CPU before memory limits meaningfully constrain execution.

Why it matters to the business

Applications that render or sanitize untrusted content through LiquidJS strip_html can be made slow or unavailable by a small number of unauthenticated requests. This can cause customer-facing outages, API timeouts, worker saturation, autoscaling cost increases, degraded queue processing, and loss of availability for services that depend on Node.js workers. Although there is no known KEV listing, ransomware association, or public exploit maturity reported in the provided data, the flaw is network-reachable, requires no authentication, and has low attack complexity, so internet-exposed applications should treat remediation as availability-critical.

How an attack unfolds

An attacker identifies an application path that accepts user-controlled content and processes it through LiquidJS, especially content that is passed to the strip_html filter during template rendering or sanitization. The attacker sends a request containing a large sequence of unterminated opener tokens, for example repeated <script strings without matching </script> closers. When the application invokes strip_html, the vulnerable regex attempts many alternative matches and backtracks quadratically. This blocks the Node.js event loop, preventing the worker from serving other requests until the regex completes. By repeating the request or sending larger payloads, the attacker can keep workers CPU-bound, exhaust available Node.js instances, and cause service-wide denial of service without needing credentials or code execution.

How to fix it

Upgrade LiquidJS to version 10.26.0 or later wherever it is used directly or transitively. If immediate upgrade is not possible, avoid applying strip_html to untrusted input, disable or replace the vulnerable filter with a parser-based HTML sanitizer, and enforce strict maximum request body sizes and field lengths before template rendering. Add request rate limits for endpoints that accept rich text or template-rendered content, and consider isolating template rendering in worker threads or separate processes so regex CPU spikes cannot block the primary request event loop. Memory limits alone should not be considered a mitigation because the vulnerability is CPU-bound rather than memory-bound.

How to confirm the fix worked

Confirm all deployed packages, lockfiles, containers, and build artifacts use LiquidJS 10.26.0 or later. For Node.js projects, inspect package-lock.json, yarn.lock, pnpm-lock.yaml, npm ls liquidjs, or equivalent software composition analysis results for vulnerable versions. Exercise representative endpoints with safe, bounded test inputs containing repeated unterminated <script or <style tokens and verify that response latency, CPU consumption, and event-loop delay do not grow disproportionately. Review application telemetry for event-loop delay, request duration, 5xx errors, and worker restarts before and after remediation. Ensure request-size and field-length controls reject oversized HTML-like payloads before they reach template rendering.

Typical attack path

  1. Find a web endpoint, API field, comment form, content import path, CMS feature, or webhook that accepts user-controlled HTML-like text.
  2. Confirm that submitted content is rendered, transformed, or sanitized by LiquidJS templates using the strip_html filter.
  3. Send a payload containing many unterminated opener tokens such as repeated <script, <style, or <!-- sequences.
  4. Trigger template rendering so the vulnerable strip_html regex runs against the crafted string.
  5. Cause prolonged V8 regex backtracking that blocks the Node.js event loop and consumes CPU.
  6. Repeat requests or increase payload size to saturate Node.js workers and cause timeouts or service unavailability.

How to detect it

Look for evidence of denial-of-service behavior correlated with requests containing large amounts of unterminated HTML-like opener tokens. Useful log sources include reverse proxy access logs, WAF logs, application request logs, Node.js application telemetry, APM traces, container metrics, Kubernetes events, autoscaler metrics, and process supervisor logs. Focus on endpoints that accept rich text, comments, descriptions, templates, previews, imports, CMS content, markdown/HTML fields, email templates, or webhook payloads. Indicators include unusually large request bodies, repeated literal strings such as <script<script<script, <style<style<style, or <!--<!--<!--, long request durations, upstream timeouts, HTTP 502/503/504 bursts, high Node.js CPU with low throughput, increased event-loop delay, worker process restarts, and autoscaling events. Because the attack does not require successful authentication or persistent malware, forensic evidence may be limited to request logs, payload captures, WAF events, and resource-exhaustion telemetry. If full request bodies are not logged, search WAF samples, error reporting payloads, APM span attributes, proxy debug logs, and packet captures collected during outage windows.

  • <script<script<script
  • <style<style<style
  • <!--<!--<!--
  • <script<script<script<script<script
  • <style<style<style<style<style
  • <!--<!--<!--<!--<!--
  • ("<script".repeat(50000))
  • '<script'.repeat(50000)
  • request body contains repeated "<script" without "</script>"
  • request body contains repeated "<style" without "</style>"
  • request body contains repeated "<!--" without "-->"
  • LiquidJS
  • strip_html
  • event loop delay
  • Event loop delay
  • upstream timed out
  • upstream prematurely closed connection
  • HTTP 504
  • HTTP 503
  • HTTP 502
  • JavaScript heap out of memory
  • worker timeout
  • npm ls liquidjs
  • liquidjs@10.25.7
  • liquidjs@10.25.6
  • node

What your security team should do

  • Inventory applications and services that use LiquidJS, including transitive dependencies in Node.js applications, static site generation pipelines, CMS features, email templating, and user-content rendering paths.
  • Prioritize internet-facing or unauthenticated endpoints that pass user-controlled content through templates or sanitization filters.
  • Upgrade LiquidJS to 10.26.0 or later and rebuild/redeploy affected containers, serverless bundles, and static generation workers.
  • Until upgraded, block or strictly limit large HTML-like payloads containing repeated <script, <style, or <!-- tokens on endpoints that render LiquidJS templates.
  • Add observability for Node.js event-loop delay, CPU saturation, request body size anomalies, 499/500/502/503/504 spikes, and worker restarts.
  • Review historical logs for suspicious long requests and CPU-bound outage windows, especially around rich-text submission, preview, import, rendering, or webhook endpoints.
  • Do not rely on LiquidJS memoryLimit as the primary mitigation for this issue; enforce pre-render input limits and upgrade the package.
  • Update dependency policies so vulnerable LiquidJS versions 10.25.7 and earlier are blocked in future builds.

The record

LiquidJS is a Shopify/GitHub Pages compatible template engine written in pure JavaScript. In versions 10.25.7 and below, the built-in strip_html filter uses a regex containing four flawed lazy-quantified alternatives, leading to ReDoS via quadratic backtracking. When the input contains many <script, <style, or <!-- opener tokens without matching closers, the V8 regex engine performs O(N²) backtracking, blocking the Node.js event loop. A single ~350 KB request ('<script'.repeat(50000)) stalls the process for ~10 seconds; cost grows quadratically with input size. The default memoryLimit: Infinity does not bound regex CPU, and even when configured strip_html only charges str.length to the limit — the regex itself runs unbounded. A single unauthenticated request containing crafted untrusted input can cause severe event-loop blocking and CPU amplification that saturates Node.js workers while bypassing memoryLimit protections. This issue has been fixed in version 10.26.0.

Affected packages

Ecosystem Package Introduced Fixed
npm liquidjs 0 10.26.0

Related vulnerabilities