Advisory Database
  • Advisories
  • Dependency Scanning
  1. npm
  2. ›
  3. liquidjs
  4. ›
  5. CVE-2026-39859

CVE-2026-39859: LiquidJS: `renderFile()` / `parseFile()` bypass configured `root` and allow arbitrary file read

April 8, 2026 (updated April 9, 2026)

liquidjs 10.25.0 documents root as constraining filenames passed to renderFile() and parseFile(), but top-level file loads do not enforce that boundary.

The published npm package liquidjs@10.25.0 on Linux 6.17.0 with Node v22.22.1. A Liquid instance configured with an empty temporary directory as root still returned the contents of /etc/hosts when renderFile('/etc/hosts') was called. I have not exhaustively checked older releases yet; 10.25.0 is the latest tested version.

Root cause:

  • src/parser/parser.ts:83-85 calls loader.lookup(file, LookupType.Root, ...) and then reads the returned file.
  • src/fs/loader.ts:38 passes type !== LookupType.Root into candidates().
  • For LookupType.Root, enforceRoot is false, so src/fs/loader.ts:47-66 accepts resolved absolute paths and fallback results without any contains() check.

This appears adjacent to the March 10, 2026 fix for CVE-2026-30952, which hardened include / render / layout but not the top-level file-loading APIs.

Proof of concept:

const fs = require('fs');
const os = require('os');
const path = require('path');
const { Liquid } = require('liquidjs');

const safeRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'liquidjs-safe-root-'));
const engine = new Liquid({ root: [safeRoot], extname: '.liquid' });

engine.renderFile('/etc/hosts').then(console.log);

Expected result: a path outside root should be rejected. Actual result: /etc/hosts is rendered successfully.

Impact: any application that treats root as a sandbox boundary and forwards attacker-controlled template names into renderFile() or parseFile() can disclose arbitrary local files readable by the server process.

Suggested fix: apply the same containment checks used for partial/layout lookups to LookupType.Root, and reject absolute or fallback paths unless they remain within an allowed root. A regression test should verify that renderFile('/etc/hosts') fails when root points to an unrelated directory.

References

  • github.com/advisories/GHSA-v273-448j-v4qj
  • github.com/harttle/liquidjs
  • github.com/harttle/liquidjs/commit/f41c1fc02fe901598f3328118b42b13bc6bc9b04
  • github.com/harttle/liquidjs/pull/870
  • github.com/harttle/liquidjs/releases/tag/v10.25.5
  • github.com/harttle/liquidjs/security/advisories/GHSA-v273-448j-v4qj
  • nvd.nist.gov/vuln/detail/CVE-2026-39859

Code Behaviors & Features

Detect and mitigate CVE-2026-39859 with GitLab Dependency Scanning

Secure your software supply chain by verifying that all open source dependencies used in your projects contain no disclosed vulnerabilities. Learn more about Dependency Scanning →

Affected versions

All versions before 10.25.5

Fixed versions

  • 10.25.5

Solution

Upgrade to version 10.25.5 or above.

Impact 5.3 MEDIUM

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N

Learn more about CVSS

Weakness

  • CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')

Source file

npm/liquidjs/CVE-2026-39859.yml

Spotted a mistake? Edit the file on GitLab.

  • Site Repo
  • About GitLab
  • Terms
  • Privacy Statement
  • Contact

Page generated Sat, 09 May 2026 12:19:09 +0000.