GCVE Workshop - 22 September 2026 (14:00-18:00), Luxembourg Before The Vulnopticon Conference - Registration

GHSA-PHJ3-59PF-CP83

Vulnerability from github – Published: 2026-07-31 19:00 – Updated: 2026-07-31 19:00
VLAI
Summary
Thumbor proportion filter allows unbounded post-transform resize leading to remote DoS
Details

Summary

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 new_width = source_width * value and new_height = source_height * value and then calls engine.resize(new_width, new_height).
  • Execution phase: proportion runs in the default POST_TRANSFORM 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., MAX_WIDTH/MAX_HEIGHT 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 by default via BUILTIN_FILTERS).
  • Either:
  • /unsafe/ URLs are allowed (ALLOW_UNSAFE_URL=True, common default in some deployments), OR
  • /unsafe/ is disabled, and the attacker has a valid signed URL (i.e., the attacker is an authorized user/partner, or otherwise can obtain signed URLs issued by a trusted signing service).

Example request 1 (signed URL)

The following request was used to reproduce the issue and causes severe resource exhaustion:

http://<host>:<port>/<url-sign>/100x100/filters:proportion(10000)/example.jpg

Example request 2 (/unsafe/)

If /unsafe/ is enabled:

http://<host>:<port>/unsafe/100x100/filters:proportion(10000)/example.jpg

Impact

  • Remote Denial of Service via CPU and/or memory exhaustion (and potentially process crash / OOM kill).
  • Exploitability depends on deployment:
  • If /unsafe/ is enabled: unauthenticated remote DoS.
  • If /unsafe/ is disabled: the attacker needs a valid signed URL (i.e., the attacker can legitimately request signed URLs, or has access to signed URLs issued for other users/partners). If signed URLs are not exposed to untrusted parties, exploitability is reduced but the risk still applies to any party who can generate/use signed URLs.

Suggested remediation

  • Enforce a strict bound on the proportion parameter (e.g., 0.0 < value <= 1.0 as documented), or define a safe maximum based on intended semantics.
Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 7.7.7"
      },
      "package": {
        "ecosystem": "PyPI",
        "name": "thumbor"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "7.8.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-53505"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-400"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-07-31T19:00:44Z",
    "nvd_published_at": null,
    "severity": "HIGH"
  },
  "details": "### Summary\nThumbor\u0027s `filters:proportion(\u003cvalue\u003e)` filter does not enforce an upper bound on `\u003cvalue\u003e` and runs in the post-transform phase. An attacker can trigger extremely large resizes (CPU/memory exhaustion) and cause denial of service.\n\n### Details\n- Filter implementation: `thumbor/filters/proportion.py`\n  - `value` is parsed as a float (`BaseFilter.DecimalNumber`) with no maximum.\n  - The filter computes `new_width = source_width * value` and `new_height = source_height * value` and then calls `engine.resize(new_width, new_height)`.\n- Execution phase: `proportion` runs in the default POST_TRANSFORM 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., `MAX_WIDTH`/`MAX_HEIGHT` applied to `req.width/req.height`).\n\nDocumentation states the `percentage` argument should be `0.0 to 1.0` (`docs/proportion.rst`), but the implementation does not enforce this constraint.\n\n### PoC\n#### Preconditions\n- The `proportion` filter is enabled (it is enabled by default via `BUILTIN_FILTERS`).\n- Either:\n  - `/unsafe/` URLs are allowed (`ALLOW_UNSAFE_URL=True`, common default in some deployments), OR\n  - `/unsafe/` is disabled, and the attacker has a valid signed URL (i.e., the attacker is an authorized user/partner, or otherwise can obtain signed URLs issued by a trusted signing service).\n\n#### Example request 1 (signed URL)\nThe following request was used to reproduce the issue and causes severe resource exhaustion:\n\n`http://\u003chost\u003e:\u003cport\u003e/\u003curl-sign\u003e/100x100/filters:proportion(10000)/example.jpg`\n\n#### Example request 2 (/unsafe/)\nIf `/unsafe/` is enabled:\n\n`http://\u003chost\u003e:\u003cport\u003e/unsafe/100x100/filters:proportion(10000)/example.jpg`\n\n### Impact\n- Remote Denial of Service via CPU and/or memory exhaustion (and potentially process crash / OOM kill).\n- Exploitability depends on deployment:\n  - If `/unsafe/` is enabled: unauthenticated remote DoS.\n  - If `/unsafe/` is disabled: the attacker needs a valid signed URL (i.e., the attacker can legitimately request signed URLs, or has access to signed URLs issued for other users/partners). If signed URLs are not exposed to untrusted parties, exploitability is reduced but the risk still applies to any party who can generate/use signed URLs.\n\n### Suggested remediation\n- Enforce a strict bound on the `proportion` parameter (e.g., `0.0 \u003c value \u003c= 1.0` as documented), or define a safe maximum based on intended semantics.",
  "id": "GHSA-phj3-59pf-cp83",
  "modified": "2026-07-31T19:00:44Z",
  "published": "2026-07-31T19:00:44Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/thumbor/thumbor/security/advisories/GHSA-phj3-59pf-cp83"
    },
    {
      "type": "WEB",
      "url": "https://github.com/thumbor/thumbor/commit/2c716119de986cfc68c7071af52a98187e006023"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/thumbor/thumbor"
    },
    {
      "type": "WEB",
      "url": "https://github.com/thumbor/thumbor/releases/tag/7.8.0"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Thumbor proportion filter allows unbounded post-transform resize leading to remote DoS"
}



Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

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…

Detection rules are retrieved from Rulezet.

Loading…

Loading…

Related by attack behaviour

Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.


Loading…