Shopify/liquid · error · Liquid::FileSystemError
Illegal template path '#
Error message
Illegal template path '#{File.expand_path(full_path)}' What it means
After expanding the template name against root, full_path re-checks that File.expand_path(full_path) still starts with File.expand_path(root); otherwise it raises Liquid::FileSystemError with the expanded path. This is the final defense against names that resolve outside the template root (e.g. via symlinks or '..' slipping past the regex).
Solutions
- Fix the template name so it resolves inside the root (remove '..' segments).
- Set root to an absolute, canonical directory (File.expand_path) when constructing LocalFileSystem.
- Remove or replace symlinks in the template directory that point outside the root.
- Log/inspect the expanded path in the message to see where the resolution went wrong.
Example fix
// before
Liquid::LocalFileSystem.new('templates/../views', '%s.liquid')
// after
Liquid::LocalFileSystem.new(File.expand_path('views'), '%s.liquid') Defensive patterns
Strategy: validation
Validate before calling
def within_root?(fs, name) File.expand_path(fs.full_path(name)).start_with?(File.expand_path(fs.root)) rescue Liquid::FileSystemError false end
Type guard
def safe_resolve(fs, name) full = File.expand_path(fs.full_path(name)) full.start_with?(File.expand_path(fs.root)) ? full : nil rescue Liquid::FileSystemError nil end
Try / catch
begin
tpl.render(ctx)
rescue Liquid::FileSystemError => e
raise unless e.message.start_with?('Illegal template path')
security_logger.warn(e.message)
render_error_page
end Prevention
- Configure root as an absolute, canonical path (File.expand_path).
- Avoid symlinks inside template directories pointing outside root.
- Never accept '..' in template names from any external source.
- Audit the template root periodically for unexpected entries.
When it happens
Trigger: A template name whose resolved absolute path escapes the configured root — typically via '..' segments, a misconfigured root, or a symlink inside the template directory pointing elsewhere.
Common situations: Configuring root with a relative or trailing-slash path that expands differently than expected; template directories containing symlinks to other locations; names combining subdirectories with '..'.
Understand the failure class
Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.
Related errors
- Illegal template name '#
- This liquid context does not allow includes.
- No such template '#
- Template.file_system=
- Nesting too deep
AI-assisted analysis of Shopify/liquid@807d45a6b3 (2026-09-08).
Data as JSON: /api/errors/6b82093bdda62852.
Report an issue: GitHub.
Appendix: source
Thrown at lib/liquid/file_system.rb:70
end
def read_template_file(template_path)
full_path = full_path(template_path)
raise FileSystemError, "No such template '#{template_path}'" unless File.exist?(full_path)
File.read(full_path)
end
def full_path(template_path)
raise FileSystemError, "Illegal template name '#{template_path}'" unless %r{\A[^./][a-zA-Z0-9_/]+\z}.match?(template_path)
full_path = if template_path.include?('/')
File.join(root, File.dirname(template_path), @pattern % File.basename(template_path))
else
File.join(root, @pattern % template_path)
end
raise FileSystemError, "Illegal template path '#{File.expand_path(full_path)}'" unless File.expand_path(full_path).start_with?(File.expand_path(root))
full_path
end
end
end
View on GitHub (pinned to 807d45a6b3)