CVE-2026-106120 Overview
LiquidJS is a Shopify and GitHub Pages compatible template engine written in pure JavaScript. Versions prior to 10.27.2 contain an information disclosure flaw [CWE-200] in the ownPropertyOnly security control. The option is designed to prevent templates from reading prototype-inherited properties, but several array operations bypass this restriction. Negative indexing, .first, .last, the first and last filters, join, reverse, slice, compact, and for-loop iteration can all read prototype-provided array elements outside readJSProperty(). Attackers who can influence prototype state and trigger affected template operations can disclose values that ownPropertyOnly is expected to hide.
Critical Impact
Template renderers using ownPropertyOnly to isolate untrusted data can leak inherited array indices, exposing values the application assumes are hidden.
Affected Products
- LiquidJS versions prior to 10.27.2
- Applications using LiquidJS with ownPropertyOnly enabled for sandboxing
- Shopify-compatible and GitHub Pages-compatible template rendering integrations
Discovery Timeline
- 2026-10-06 - CVE-2026-106120 published to NVD
- 2026-10-06 - Last updated in NVD database
- Fixed in release - LiquidJS v10.27.2 published on GitHub
Technical Details for CVE-2026-106120
Vulnerability Analysis
The ownPropertyOnly option in LiquidJS is intended to restrict template reads to own properties, preventing prototype pollution and inherited data leakage. The control is centralized in readJSProperty(), which checks hasOwnProperty before returning values. However, array-handling code paths read elements directly through index access or utility helpers that skip this check.
Affected code paths include negative index resolution, the .first and .last accessors, the first, last, join, reverse, slice, and compact filters, and for-loop iteration. Any of these paths can return prototype-provided elements when the array prototype has been modified or when the input object inherits numeric indices.
An attacker who controls prototype state through a secondary pollution vector, or who supplies objects with inherited array-index data, can craft templates that disclose values hidden by ownPropertyOnly. Direct positive indexing against ordinary objects remains blocked. The scope is limited to confidentiality, so integrity and availability are not directly impacted.
Root Cause
The array utility functions and loop iterator bypass readJSProperty() and read elements through unchecked JavaScript property access. The ownPropertyOnly enforcement was never applied uniformly across the array read surface.
Attack Vector
Exploitation requires low privileges and the ability to render a Liquid template that references attacker-influenced data. The flaw is reachable over the network wherever LiquidJS renders templates against partially untrusted input or shared prototype state.
// Patch: src/context/context.ts
import { __assign } from 'tslib'
import { NormalizedFullOptions, defaultOptions, RenderOptions } from '../liquid-options'
import { createScope, Scope } from './scope'
-import { hasOwnProperty, isArray, isNil, isUndefined, isString, isFunction, toLiquid, InternalUndefinedVariableError, toValueSync, isObject, Limiter, toValue } from '../util'
+import { hasOwnProperty, isArray, isNil, isUndefined, isString, isFunction, isNumber, toLiquid, InternalUndefinedVariableError, toValueSync, isObject, Limiter, toValue, readArrayElement } from '../util'
type PropertyKey = string | number;
Source: GitHub Commit 552819a. The patch introduces a new readArrayElement helper and applies it across context resolution and array filters so that every array read honors ownPropertyOnly.
// Patch: src/filters/array.ts
-import { toArray, argumentsToValue, toValue, stringify, caseInsensitiveCompare, orderedCompare, isArray, isNil, last as arrayLast, isArrayLike, toEnumerable } from '../util'
+import { toArray, argumentsToValue, toValue, stringify, caseInsensitiveCompare, orderedCompare, isArray, isNil, isArrayLike, readArrayElement, toEnumerable } from '../util'
import { arrayIncludes, equals, evalToken, isTruthy } from '../render'
import { Value, FilterImpl } from '../template'
import { Tokenizer } from '../parser'
Source: GitHub Commit 552819a. The array filter module removes the direct arrayLast import and routes element reads through the hardened helper.
Detection Methods for CVE-2026-106120
Indicators of Compromise
- Rendered template output containing data that should be excluded by ownPropertyOnly, such as values matching known prototype keys.
- Node.js processes loading LiquidJS packages at versions below 10.27.2 identified through SBOM or lockfile inventory.
- Template inputs or upstream libraries that modify Array.prototype numeric indices prior to rendering.
Detection Strategies
- Inventory JavaScript dependencies using npm ls liquidjs or lockfile scans and flag any resolution below 10.27.2.
- Review template code for use of .first, .last, first, last, join, reverse, slice, compact, negative indexing, and for loops over user-controlled arrays.
- Add unit tests that assert prototype-inherited indices are not reachable when ownPropertyOnly: true is set.
Monitoring Recommendations
- Monitor application logs for template rendering errors or unexpected output values on routes that process untrusted data.
- Alert on new deployments of LiquidJS packages below 10.27.2 through continuous software composition analysis.
- Track upstream advisories referenced in GHSA-fwxr-j5w2-587m for related guidance.
How to Mitigate CVE-2026-106120
Immediate Actions Required
- Upgrade LiquidJS to 10.27.2 or later across all applications and build pipelines.
- Audit any code paths that modify Array.prototype and remove inherited numeric indices on untrusted objects.
- Re-run template security tests after upgrade to confirm ownPropertyOnly enforcement.
Patch Information
The fix is included in LiquidJS Release v10.27.2 and tracked in Pull Request #924. Full technical context is documented in GHSA-fwxr-j5w2-587m.
Workarounds
- Avoid depending on ownPropertyOnly as a sole security boundary for untrusted template data until the upgrade is complete.
- Sanitize or deep-clone input objects with Object.create(null) prototypes before passing them to the Liquid engine.
- Restrict template authors from using .first, .last, and the affected filters when operating on untrusted arrays.
# Upgrade LiquidJS to the patched release
npm install liquidjs@^10.27.2
# Verify installed version
npm ls liquidjs
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

