Cloudanix VulnDB

CVE-2026-35525

High · 7.5

CVSS

7.5

EPSS

0.5%

Published

Apr 8, 2026

CISA due date

—

Cloudanix analysis

Next patch cycle SSVC: Track

A flaw in the template engine can let someone who can add template files trick the application into revealing sensitive files from the server.

Chainable
Exploitation
Remote Unauthenticated
Attacker needs
None
Complexity
Moderate
Impact
Data Exposure
Component
Library
Class
Path Traversal
Remediation
Upgrade
Effort
Medium
Patch risk
Low

What it actually does

LiquidJS versions before 10.25.3 can enforce template root restrictions against the requested path string rather than the resolved filesystem target. For include, render, and layout operations, a pathname under an allowed partials or layouts directory may pass the containment check even when that file is a symbolic link to a location outside the allowed root. When LiquidJS opens the file, the operating system follows the symlink and renders the external target. The primary technical impact is unauthorized local file read through template rendering, exposing secrets, configuration files, application source, environment data, or mounted credentials accessible to the application process. Integrity and availability impact are not the main concern unless exposed files enable follow-on compromise.

Why it matters to the business

Applications that allow users, repositories, archives, themes, plugins, or mounted content to influence LiquidJS template directories may unintentionally expose sensitive server-side files. This can lead to credential theft, disclosure of application secrets, source-code exposure, cloud or Kubernetes token leakage, and follow-on access to internal systems. Although this is not currently listed in CISA KEV and has low EPSS at the time of assessment, the issue is straightforward to exploit where attackers can place symlinks under trusted template roots, so internet-facing theme/template upload workflows and CI/CD-driven template deployments should be prioritized.

How an attack unfolds

An attacker first needs a way to place or influence files under a LiquidJS trusted template root, such as uploaded themes, extracted archives, repository-controlled templates, mounted content, or plugin-managed template directories. Instead of adding a normal .liquid file, the attacker creates a symbolic link whose path appears to reside inside the allowed partials or layouts directory but whose target points to a sensitive file outside that directory. The attacker then causes the application to render that template through a LiquidJS include, render, or layout directive. Vulnerable LiquidJS versions validate the apparent path as being under the configured root, then open the symlink target. The rendered response may disclose the contents of the external file to the attacker or place it into generated output, logs, emails, previews, or cached pages.

How to fix it

Upgrade LiquidJS to version 10.25.3 or later. Where package manifests are used, pin or require liquidjs >= 10.25.3 and rebuild/redeploy all dependent services, containers, serverless packages, and static generation pipelines that bundle LiquidJS. If immediate upgrade is not possible, prevent symbolic links from being created or retained under LiquidJS partials and layouts roots; reject symlinks during upload, archive extraction, repository import, and deployment packaging; perform realpath-based containment checks before rendering; run template rendering with the least filesystem privileges possible; and isolate template roots from secrets, service account tokens, environment files, source repositories, and host-mounted sensitive paths. Treat user-supplied themes and archives as untrusted content and validate them before extraction or activation.

How to confirm the fix worked

Confirm the deployed dependency tree resolves LiquidJS to 10.25.3 or later using package-lock, pnpm-lock, yarn.lock, SBOM, container image scans, or runtime package inspection. Search all built artifacts and images, not only source repositories, because bundled JavaScript dependencies may persist in containers or serverless packages. Verify template upload, archive extraction, repository sync, and deployment processes reject or remove symlinks under partials and layouts directories. As a safe validation test, create a symlink inside a non-production template root that points to a harmless file outside that root and confirm include, render, and layout operations fail rather than render the target. Review filesystem permissions to ensure the application process cannot read unnecessary sensitive files.

Typical attack path

  1. Identify an application feature or deployment path that accepts or syncs LiquidJS templates, themes, archives, repository content, or mounted files.
  2. Place a symbolic link under an allowed partials or layouts root using a filename that appears legitimate, such as a .liquid partial.
  3. Point the symlink to a sensitive file readable by the application process outside the allowed template root.
  4. Trigger rendering through a LiquidJS include, render, or layout operation that references the symlinked template path.
  5. Retrieve the rendered output from the application response, preview, generated page, cache, log, or downstream message.
  6. Use any exposed secrets, tokens, configuration values, or source code for follow-on access or lateral movement.

How to detect it

Look for evidence that symlinks were introduced under LiquidJS partials or layouts roots and then rendered through include, render, or layout tags. Useful sources include application access logs, template rendering logs, CMS/theme upload logs, archive extraction logs, repository commit history, CI/CD deployment logs, file integrity monitoring events, container image layer contents, and EDR filesystem telemetry. Search for symlink creation or extraction events where the link resides in a template directory but resolves outside that directory, especially to credential, configuration, environment, source-code, or service-account paths. Review web requests or preview/render actions occurring shortly after theme uploads or repository commits. Inspect generated pages, caches, emails, or rendered artifacts for leaked file contents such as passwd-format lines, private keys, cloud credential blocks, environment variable dumps, or Kubernetes service account tokens. If exploitation is suspected, preserve the uploaded archive or repository revision, the resolved symlink metadata, rendered output, application logs, and package version evidence before cleanup.

  • {% include
  • {% render
  • {% layout
  • /etc/passwd
  • /etc/shadow
  • /proc/self/environ
  • /proc/self/cmdline
  • /var/run/secrets/kubernetes.io/serviceaccount/token
  • /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
  • /.aws/credentials
  • /.aws/config
  • id_rsa
  • id_ed25519
  • -----BEGIN PRIVATE KEY-----
  • -----BEGIN OPENSSH PRIVATE KEY-----
  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY
  • DATABASE_URL
  • SECRET_KEY
  • SESSION_SECRET
  • JWT_SECRET
  • NODE_ENV=

What your security team should do

  • Inventory all applications and build pipelines using LiquidJS, including transitive use by static-site generators, CMS/theme systems, documentation tooling, and email/template rendering services.
  • Prioritize internet-facing or multi-tenant systems where users can upload themes, templates, archives, repository content, plugins, or other files that land under template roots.
  • Upgrade LiquidJS to 10.25.3 or later and redeploy affected workloads from clean builds.
  • Add CI/CD and upload-time controls that reject symlinks in template directories and safely extract archives without preserving unsafe links.
  • Scan existing partials and layouts directories for symlinks that resolve outside the configured template roots.
  • Reduce blast radius by running rendering processes with least-privilege filesystem access and without direct access to cloud credentials, Kubernetes tokens, SSH keys, or application secrets.
  • Review recent template changes, theme uploads, archive imports, and repository commits for suspicious symlinks or include/render/layout references.
  • If suspicious exposure is found, rotate any secrets that may have been readable by the rendering process and investigate downstream use of those credentials.

The record

LiquidJS is a Shopify / GitHub Pages compatible template engine in pure JavaScript. Prior to 10.25.3, for {% include %}, {% render %}, and {% layout %}, LiquidJS checks whether the candidate path is inside the configured partials or layouts roots before reading it. That check is path-based, not realpath-based. Because of that, a file like partials/link.liquid passes the directory containment check as long as its pathname is under the allowed root. If link.liquid is actually a symlink to a file outside the allowed root, the filesystem follows the symlink when the file is opened and LiquidJS renders the external target. So the restriction is applied to the path string that was requested, not to the file that is actually read. This matters in environments where an attacker can place templates or otherwise influence files under a trusted template root, including uploaded themes, extracted archives, mounted content, or repository-controlled template trees. This vulnerability is fixed in 10.25.3.

Affected packages

Ecosystem Package Introduced Fixed
npm liquidjs 0 10.25.3

Related vulnerabilities