Skip to content

← Public intelligence

PyPI package

thumbor

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.

  1. High, CVSS 8.7PyPIPublished

    Thumbor has path traversal via post-validation URL decoding bypass in file_loader

    CVE-2026-53502 · GHSA-cj54-hpcc-gj6h

    Affected
    • PyPI thumbor <= 7.7.7
    Fixed in
    7.8.0· Vendor fix available
    Issue
    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.

    Sources:github.comSource checked Evidence →
  2. High, CVSS 7.5PyPIPublished

    Thumbor proportion filter allows unbounded post-transform resize leading to remote DoS

    CVE-2026-53505 · GHSA-phj3-59pf-cp83

    Affected
    • PyPI thumbor <= 7.7.7
    Fixed in
    7.8.0· Vendor fix available
    Issue
    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.

    Sources:github.comSource checked Evidence →
  3. High, CVSS 7.5PyPIPublished

    Thumbor has Regex Denial of Service (ReDoS) in convolution filter

    CVE-2026-53504 · GHSA-5vjc-7cxw-4w6j

    Affected
    • PyPI thumbor <= 7.7.7
    Fixed in
    7.8.0· Vendor fix available
    Issue
    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.

    Sources:github.comSource checked Evidence →
  4. High, CVSS 7.5PyPIPublished

    Thumbor convolution filter allows divide-by-zero in C extension leading to remote DoS

    CVE-2026-53503 · GHSA-cqjp-jf4r-h5q9

    Affected
    • PyPI thumbor <= 7.7.7
    Fixed in
    7.8.0· Vendor fix available
    Issue
    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.

    Sources:github.comSource checked Evidence →
  5. High, CVSS 8.2PyPIPublished

    Thumbor has HMAC validation bypass via multiple .replace() calls when removing URL signature

    CVE-2026-53501 · GHSA-mw3h-qjxj-6xg9

    Affected
    • PyPI thumbor <= 7.7.7
    Fixed in
    7.8.0· Vendor fix available
    Issue
    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.

    Sources:github.comSource checked Evidence →
  6. High, CVSS 8.2PyPIPublished

    Thumbor treats ALLOWED_SOURCES string patterns as unescaped regex, allowing hostname bypass via wildcard dot

    CVE-2026-53500 · GHSA-6x26-6r6f-m537

    Affected
    • PyPI thumbor <= 7.7.7
    Fixed in
    7.8.0· Vendor fix available
    Issue
    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.

    Sources:github.comSource checked Evidence →