Severity by source
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
Network-reachable via single HTTP request, no auth (default ALLOW_UNSAFE_URL=True), no interaction needed, confidentiality-only impact with no scope change.
Primary rating from Vendor (github).
CVSS VectorVendor: github
Lifecycle Timeline
4Blast Radius
ecosystem impact- 24 pypi packages depend on thumbor (24 direct, 0 indirect)
Ecosystem-wide dependent count for version 7.8.0.
DescriptionCVE.org
Thumbor is an open-source photo thumbnail service by globo.com. Prior to 7.8.0, file_loader decodes percent-encoded path segments after its root-boundary validation, allowing traversal outside FILE_LOADER_ROOT_PATH through watermark or frame filter input. This issue is fixed in 7.8.0.
AnalysisAI
Arbitrary file read in Thumbor prior to 7.8.0 allows unauthenticated remote attackers to read any file accessible to the thumbor process by supplying percent-encoded path traversal sequences via the watermark or frame filter parameters. The root cause is a decode-after-check flaw in file_loader: the security boundary check runs on the raw encoded path (%2e%2e is treated as a literal directory name and passes the abspath/startswith guard), then unquote() is called afterward, converting %2e%2e into real .. segments that the OS then resolves outside FILE_LOADER_ROOT_PATH. A public proof-of-concept exploit is included in the GitHub Security Advisory (GHSA-cj54-hpcc-gj6h); no active exploitation has been confirmed by CISA KEV at time of analysis.
Technical ContextAI
Thumbor (pip package thumbor) is a Python-based open-source image processing and thumbnailing service. The vulnerable component is thumbor/loaders/file_loader.py, which handles loading source images from the local filesystem. The CWE-22 (Path Traversal) root cause is a classic TOCTOU-style validation ordering error: the security check (abspath()+startswith()) operated on the raw, still-encoded path string. Because Python's os.path.abspath() does not decode percent-encoded characters, %2e%2e is treated as a literal two-character directory name, so the root-boundary check passes. The subsequent urllib.parse.unquote() call - intended for backwards compatibility with filenames containing literal percent-encoded characters - then converts %2e%2e into .. before the path is used for file I/O. The watermark and frame filters are particularly exploitable because, unlike the main image URL flow (which applies quote() in imaging.py), they pass their URL parameters directly to file_loader without re-encoding. Double-encoding (%252e → Tornado HTTP layer decodes to %2e → file_loader unquote decodes to .) enables bypass through the Tornado web server's own decoding stage as well. The fix (commit 3b986d1) moves unquote() to execute before the security check and replaces startswith() with os.path.commonpath() to prevent sibling-directory bypass attacks.
RemediationAI
Upgrade Thumbor to version 7.8.0 or later, which is available at https://github.com/thumbor/thumbor/releases/tag/7.8.0 and via pip (pip install --upgrade thumbor). The fix is confirmed by commit 3b986d13677b30fe6651c8c72ebb25957ac0a40d. If immediate upgrade is not possible, the most effective compensating control is to set ALLOW_UNSAFE_URL=False in the Thumbor configuration and require HMAC-signed URLs - this requires all URL parameters, including filter paths, to be cryptographically signed, preventing an unauthenticated attacker from supplying arbitrary watermark/frame paths (trade-off: all image URLs must be pre-signed by the application backend). A secondary control is to place Thumbor behind a reverse proxy that strips or rejects requests containing %25 (double-encoded percent signs) in filter parameter values, targeting the %252e bypass vector specifically - note this may break legitimate double-encoded filenames. Running Thumbor as a low-privilege OS user with minimal filesystem access (e.g., restricted to the media root via filesystem permissions or a chroot/container) limits the blast radius of exploitation without blocking the attack itself.
Same weakness CWE-22 – Path Traversal
View allSame technique Path Traversal
View allShare
External POC / Exploit Code
Leaving vuln.today
EUVD-2026-51612
GHSA-cj54-hpcc-gj6h