GHSA-8P4X-WR7X-3788
Vulnerability from github – Published: 2026-05-11 14:57 – Updated: 2026-05-11 14:57
VLAI
Summary
python-liquid: Absolute paths escape filesystem loader search path
Details
Impact
The built-in FileSystemLoader and CachingFileSystemLoader do not guard against reading files outside their search paths when given an absolute path to resolve. This allows malicious template authors to load and render arbitrary files via the {% include %} and {% render %} tags. Targeted files would need to contain valid Liquid markup and be readable by the application process.
Patches
The issue is fixed in version 2.2.0 with the inclusion of a template_path.is_absolute() condition in liquid/builtin/loaders/file_system_loader.py.
if os.path.pardir in template_path.parts or template_path.is_absolute():
raise TemplateNotFoundError(template_name)
Workarounds
Create a custom template loader by inheriting from FileSystemLoader and overriding resolve_path(). Use an instance of the custom loader as the loader argument when instantiating your Liquid environment.
import os
from pathlib import Path
from liquid import Environment
from liquid import FileSystemLoader
from liquid.exceptions import TemplateNotFoundError
class MyFileSystemLoader(FileSystemLoader):
def resolve_path(self, template_name: str) -> Path:
template_path = Path(template_name)
if self.ext and not template_path.suffix:
template_path = template_path.with_suffix(self.ext)
if os.path.pardir in template_path.parts or template_path.is_absolute():
raise TemplateNotFoundError(template_name)
for path in self.search_path:
source_path = path.joinpath(template_path)
if not source_path.exists():
continue
return source_path
raise TemplateNotFoundError(template_name)
env = Environment(loader=MyFileSystemLoader("path/to/templates/"))
Severity
{
"affected": [
{
"package": {
"ecosystem": "PyPI",
"name": "python-liquid"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "2.2.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-45017"
],
"database_specific": {
"cwe_ids": [
"CWE-22"
],
"github_reviewed": true,
"github_reviewed_at": "2026-05-11T14:57:43Z",
"nvd_published_at": null,
"severity": "HIGH"
},
"details": "### Impact\nThe built-in `FileSystemLoader` and `CachingFileSystemLoader` do not guard against reading files outside their search paths when given an absolute path to resolve. This allows malicious template authors to load and render arbitrary files via the `{% include %}` and `{% render %}` tags. Targeted files would need to contain valid Liquid markup and be readable by the application process.\n\n### Patches\nThe issue is fixed in version 2.2.0 with the inclusion of a `template_path.is_absolute()` condition in `liquid/builtin/loaders/file_system_loader.py`.\n\n```python\n if os.path.pardir in template_path.parts or template_path.is_absolute():\n raise TemplateNotFoundError(template_name)\n```\n\n### Workarounds\n\nCreate a custom template loader by inheriting from `FileSystemLoader` and overriding `resolve_path()`. Use an instance of the custom loader as the `loader` argument when instantiating your Liquid environment. \n\n```python\nimport os\nfrom pathlib import Path\n\nfrom liquid import Environment\nfrom liquid import FileSystemLoader\nfrom liquid.exceptions import TemplateNotFoundError\n\n\nclass MyFileSystemLoader(FileSystemLoader):\n def resolve_path(self, template_name: str) -\u003e Path:\n template_path = Path(template_name)\n\n if self.ext and not template_path.suffix:\n template_path = template_path.with_suffix(self.ext)\n\n if os.path.pardir in template_path.parts or template_path.is_absolute():\n raise TemplateNotFoundError(template_name)\n\n for path in self.search_path:\n source_path = path.joinpath(template_path)\n if not source_path.exists():\n continue\n return source_path\n\n raise TemplateNotFoundError(template_name)\n\n\nenv = Environment(loader=MyFileSystemLoader(\"path/to/templates/\"))\n```",
"id": "GHSA-8p4x-wr7x-3788",
"modified": "2026-05-11T14:57:43Z",
"published": "2026-05-11T14:57:43Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/jg-rp/liquid/security/advisories/GHSA-8p4x-wr7x-3788"
},
{
"type": "PACKAGE",
"url": "https://github.com/jg-rp/liquid"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "python-liquid: Absolute paths escape filesystem loader search path"
}
Loading…
Loading…
Experimental. This forecast is provided for visualization only and may change without notice. Do not use it for operational decisions.
Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.
Sightings
| Author | Source | Type | Date | Other |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.
Loading…
Loading…