CVE-2026-30952: liquidjs has a path traversal fallback vulnerability

Published Mar 10, 2026
·
Updated

Impact The layout, render, and include tags allow arbitrary file access via absolute paths (either as string literals or through Liquid variables when dynamicPartials: true is enabled). This poses a security risk when malicious users are allowed to control the template content or specify the filepath to be included as a Liquid variable.

Patches The issue is fixed via #855 and published version 10.25.0 on npm.

Workarounds Change the files in build time In build time, through Shell script or Webpack string-replace-loader, change the file content of correxponding file (depending on your package type, for CommonJS it's dist/liquid.node.js) under dist/,

diff if (fs.fallback !== undefined) { const filepath = fs.fallback(file) - if (filepath !== undefined) yield filepath + if (filepath !== undefined) { + for (const dir of dirs) { + if (!enforceRoot || this.contains(dir, filepath)) { + yield filepath + break + } + } } }

Overriding by fs LiquidJS option Adding a fs option to override the default fs implementation:

javascript const { statSync, readFileSync, promises: { stat, readFile } } = require('fs') const { resolve, extname, dirname, sep } = require('path')

const fs = { exists: async (fp) => { try { await stat(fp); return true; } catch { return false } }, existsSync: (fp) => { try { statSync(fp); return true } catch { return false } }, resolve: (root, file, ext) => resolve(root, file + (extname(file) ? '' : ext)), contains: (root, file) => { const r = resolve(root) return file.startsWith(r.endsWith(sep) ? r : r + sep) }, readFile: (fp) => readFile(fp, 'utf8'), readFileSync: (fp) => readFileSync(fp, 'utf8'), fallback: () => undefined, dirname, sep };

const engine = new Liquid({ fs })

References Discussions: https://github.com/harttle/liquidjs/pull/851 Code fix: https://github.com/harttle/liquidjs/pull/855

Other sources

Impact The layout, render, and include tags allow arbitrary file access via absolute paths (either as string literals or through Liquid variables, the latter require dynamicPartials: true, which is the default). This poses a security risk when malicious users are allowed to control the template content or specify the filepath to be included as a Liquid variable.

Patches The root cause is LiquidJS allows require.resolve() as fallback but doesn't limit the directories it can resolve to. The issue is fixed via #855 and published version 10.25.0 on npm.

Workarounds Change the files in build time In build time, through Shell script or Webpack string-replace-loader, change the file content of correxponding file (depending on your package type, for CommonJS it's dist/liquid.node.js) under dist/,

diff if (fs.fallback !== undefined) { const filepath = fs.fallback(file) - if (filepath !== undefined) yield filepath + if (filepath !== undefined) { + for (const dir of dirs) { + if (!enforceRoot || this.contains(dir, filepath)) { + yield filepath + break + } + } } }

Overriding by fs LiquidJS option Adding a fs option to override the default fs implementation:

javascript const { statSync, readFileSync, promises: { stat, readFile } } = require('fs') const { resolve, extname, dirname, sep } = require('path')

const fs = { exists: async (fp) => { try { await stat(fp); return true; } catch { return false } }, existsSync: (fp) => { try { statSync(fp); return true } catch { return false } }, resolve: (root, file, ext) => resolve(root, file + (extname(file) ? '' : ext)), contains: (root, file) => { const r = resolve(root) return file.startsWith(r.endsWith(sep) ? r : r + sep) }, readFile: (fp) => readFile(fp, 'utf8'), readFileSync: (fp) => readFileSync(fp, 'utf8'), fallback: () => undefined, dirname, sep };

const engine = new Liquid({ fs })

References Discussions: https://github.com/harttle/liquidjs/pull/851 Code fix: https://github.com/harttle/liquidjs/pull/855

GitHub

liquidjs is a Shopify / GitHub Pages compatible template engine in pure JavaScript. Prior to 10.25.0, the layout, render, and include tags allow arbitrary file access via absolute paths (either as string literals or through Liquid variables, the latter require dynamicPartials: true, which is the default). This poses a security risk when malicious users are allowed to control the template content or specify the filepath to be included as a Liquid variable. This vulnerability is fixed in 10.25.0.

NVD

Affected Software

2 affected componentsFixes available
npm/liquidjs<10.25.0
10.25.0
LiquidJS Liquidjs Node.js<10.25.0

Event History

Mar 10, 2026
Advisory Published
via GitHub·01:04 AM
Data Sourced
via GitHub·01:04 AM
DescriptionWeaknessAffected Software
CVE Published
via MITRE·08:25 PM
Data Sourced
via MITRE·08:25 PM
DescriptionWeakness
Data Sourced
via NVD·09:16 PM
DescriptionSeverityWeakness
Data Sourced
via NVD·09:16 PM
RemedyAffected Software

Frequently Asked Questions

1

What is the severity of CVE-2026-30952?

CVE-2026-30952 is considered a high severity vulnerability due to the potential for arbitrary file access.

2

How do I fix CVE-2026-30952?

To fix CVE-2026-30952, upgrade to liquidjs version 10.25.1 or later, which addresses the vulnerability.

3

What are the implications of CVE-2026-30952?

CVE-2026-30952 allows unauthorized users to access files on the server, leading to possible data exposure or manipulation.

4

Which versions of liquidjs are affected by CVE-2026-30952?

CVE-2026-30952 affects versions of liquidjs up to and including 10.25.0.

5

Is CVE-2026-30952 exploitable in all configurations of liquidjs?

CVE-2026-30952 is exploitable when `dynamicPartials: true` is enabled, allowing user-controlled content.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203