Open actionable advisories and recorded vendor fixes. This public package view has no inventory attached and cannot establish whether your deployment is affected. A vendor fix never resolves your finding; verify your installed version and the source guidance.
Open advisories
6 actionable advisories, newest first. Withdrawn advisories and news are excluded. Coverage is partial.
The fileloader 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. Affected code thumbor/loaders/fileloader.py lines 28-49: 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). PoC Flow: 1. %252e%252e arrives at Tornado, decoded to %2e%2e 2. Watermark filter passes %2e%2e/%2e%2e/.../etc/passwd to fileloader 3. join(ROOT, '%2e%2e/...') = ROOT/%2e%2e/... 4. abspath() sees %2e%2e as literal dir name (no dots to resolve) 5. startswith(ROOT) = True (passes check) 6. exists() returns False (literal %2e%2e dir doesn't exist) 7. unquote() converts %2e%2e to .. 8. OS resolves .. → reads files outside ROOT Prerequisites - LOADER =…
Recommended action: Upgrade to 7.8.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Thumbor's filters:proportion(<value) filter does not enforce an upper bound on <value and runs in the post-transform phase. An attacker can trigger extremely large resizes (CPU/memory exhaustion) and cause denial of service. Details - Filter implementation: thumbor/filters/proportion.py - value is parsed as a float (BaseFilter.DecimalNumber) with no maximum. - The filter computes newwidth = sourcewidth value and newheight = sourceheight value and then calls engine.resize(newwidth, newheight). - Execution phase: proportion runs in the default POSTTRANSFORM phase (after the main transform pipeline). This means it can effectively bypass request-level size clamping that happens earlier in the request lifecycle (e.g., MAXWIDTH/MAXHEIGHT applied to req.width/req.height). Documentation states the percentage argument should be 0.0 to 1.0 (docs/proportion.rst), but the implementation does not enforce this constraint. PoC Preconditions - The proportion filter is enabled (it is enabled…
Recommended action: Upgrade to 7.8.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
The regular expression used to parse the convolution filter exhibits exponential-time backtracking for certain inputs, enabling a Regular Expression Denial of Service (ReDoS). Details The RegExp for convolution is defined as convolution\((?:\s((?:[-]?[\d]+\.?[\d][;])(?:[-]?[\d]+\.?[\d]))\s)(?:,\s([\d]+)\s)(?:,\s([Tt]rue|[Ff]alse|1|0)\s)?\). Within this expression a dangerous subpattern effectively behaves like (\d+),\d+. PoC A filter string containing many repeated values will exhaust re.match: - convolution(-11;-11;-11;-11;-11;-11;-11;-11;-11;-11;-11;-11;-11;-11;-11;-11;-11;-11;-11;-11;-11;-11;-11;-11;-11;-11;-11;-11;-11;-11) - http://localhost:8888/unsafe/0x0/smart/filters:convolution(-11;-11;-11;-11;-11;-11;-11;-11;-11;-11;-11;-11;-11;-11;-11;-11;-11;-11;-11;-11;-11;-11;-11;-11;-11;-11;-11;-11;-11;-11)/x.png The evaluation occurs on https://github.com/thumbor/thumbor/blob/master/thumbor/filters/init.py#L189. Impact A specially crafted URL will lead to denial of service, as…
Recommended action: Upgrade to 7.8.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Thumbor's filters:convolution(<matrix, <columns, <shouldnormalize) filter passes the user-controlled <columns value to a C extension (thumbor/ext/filters/convolution.c) where it is used as a divisor (for % and /) without validating columns 0. When columns=0, the C code triggers undefined behavior; on x8664 this reliably results in a fatal divide-by-zero trap (SIGFPE) and crashes the Thumbor process (confirmed on Linux x8664 and macOS Intel x8664), causing a remote denial of service. Details Root cause The Python filter accepts columns=0, and the native C extension uses columnscount as a divisor without validating it. 1) Python filter entry point allows columns=0 (thumbor/filters/convolution.py): BaseFilter.PositiveNumber matches "0" (thumbor/filters/init.py): 2) C extension divides/modulos by columnscount without a zero check (thumbor/ext/filters/convolution.c): PoC Test environment - Linux x8664 Preconditions - The convolution filter is enabled (it is enabled by default via…
Recommended action: Upgrade to 7.8.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
HMAC validation bypass via multiple .replace() calls when removing URL signature Summary Thumbor’s HMAC validation can be bypassed due to the use of Python’s .replace() when removing the signature from the URL before validation. Since .replace() removes all occurrences of the substring, an attacker can insert the same signature multiple times in the URL and manipulate the final URL used for validation. This allows crafting URLs where the validated string differs from the actual requested resource, enabling loading images from unintended domains or paths. Details Thumbor signs URLs using HMAC-SHA1 to prevent abuse such as loading arbitrary external images or invoking filters without authorization. During request validation, Thumbor removes the signature from the request URL before recalculating the HMAC. The relevant code: The issue is that .replace() removes every occurrence of the substring in the URL, not just the first one. Because the signature itself appears in the URL, an…
Recommended action: Upgrade to 7.8.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
The ALLOWEDSOURCES configuration is meant to restrict which hosts Thumbor's HTTP loader may fetch images from. Plain-string entries in that list (the overwhelming majority of real-world and documented configurations) are passed directly to re.match() without escaping. Because . is a regex wildcard, every dot in a domain name becomes a bypass vector: s.glbimg.com silently matches sXglbimgYcom, sAglbimg.com, and any other hostname that differs only at a dot position. This undermines the primary SSRF defence that ALLOWEDSOURCES is intended to provide. Affected component thumbor/loaders/httploader.py — validate() Proof of concept Root cause thumbor/loaders/httploader.py (before fix): Impact An attacker who can influence the image source URL passed to Thumbor can fetch images from arbitrary hosts, bypassing the ALLOWEDSOURCES allowlist. Preconditions: - ALLOWEDSOURCES contains at least one plain-string entry (the common case; all official documentation examples use plain strings).…
Recommended action: Upgrade to 7.8.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.