OSV 1.4.0 · github-reviewed · 修改于 2026-08-01 03:03
发布时间
2026-08-01 03:03
GitHub 审查时间
2026-08-01 03:03
NVD 发布时间
—
源文件
advisories/github-reviewed/2026/07/GHSA-cj54-hpcc-gj6h/GHSA-cj54-hpcc-gj6h.json
The file_loader performs unquote() on the file path AFTER the abspath() + startswith() security check. An attacker can use percent-encoded path traversal sequences (%2e%2e for ..) that pass the security check as literal directory names, but are then decoded to actual .. traversal sequences.
thumbor/loaders/file_loader.py lines 28-49:
async def load(context, path):
file_path = join(
context.config.FILE_LOADER_ROOT_PATH.rstrip("/"), path.lstrip("/")
)
file_path = abspath(file_path)
inside_root_path = file_path.startswith( # Security check
abspath(context.config.FILE_LOADER_ROOT_PATH)
)
result = LoaderResult()
if not inside_root_path:
result.error = LoaderResult.ERROR_NOT_FOUND
result.successful = False
return result
if not exists(file_path):
file_path = unquote(file_path) # unquote AFTER check!
if exists(file_path) and isfile(file_path):
with open(file_path, "rb") as source_file:
...
The watermark and frame filters pass their URL parameters directly to the loader without re-encoding (unlike the main image URL flow which applies quote() in imaging.py line 37).
# Read /etc/passwd via watermark filter path traversal
# %252e is double-encoded: Tornado decodes to %2e, filter passes to file_loader,
# file_loader unquote decodes %2e to .
curl 'http://thumbor-host:8888/unsafe/filters:watermark(%252e%252e/%252e%252e/%252e%252e/%252e%252e/etc/passwd,0,0,100)/some-valid-image.jpg'
Flow:
%252e%252e arrives at Tornado, decoded to %2e%2e%2e%2e/%2e%2e/.../etc/passwd to file_loaderjoin(ROOT, '%2e%2e/...') = ROOT/%2e%2e/...abspath() sees %2e%2e as literal dir name (no dots to resolve)startswith(ROOT) = True (passes check)exists() returns False (literal dir doesn't exist)%2e%2eunquote() converts %2e%2e to .... → reads files outside ROOTLOADER = thumbor.loaders.file_loader (or file_loader_http_fallback)ALLOW_UNSAFE_URL = True (this is the default)Arbitrary file read on the thumbor server. When the file is a valid image format, its content is returned in the response overlaid as a watermark. Can be used to read configuration files, secrets, private keys, etc.