PyPI · thumbor
Thumbor proportion filter allows unbounded post-transform resize leading to remote DoS
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.
thumbor/filters/proportion.pyvalue is parsed as a float (BaseFilter.DecimalNumber) with no maximum.new_width = source_width * value and new_height = source_height * value and then calls engine.resize(new_width, new_height).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.
proportion filter is enabled (it is enabled by default via BUILTIN_FILTERS)./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).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
If /unsafe/ is enabled:
http://<host>:<port>/unsafe/100x100/filters:proportion(10000)/example.jpg
/unsafe/ is enabled: unauthenticated remote DoS./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.proportion parameter (e.g., 0.0 < value <= 1.0 as documented), or define a safe maximum based on intended semantics.Is your project exposed to this? Stateward checks every dependency on every pull request and flags it only if your code actually reaches it.
Check my repoSources: CISA KEV (public domain), OSV.dev & GitHub Advisory Database (CC-BY-4.0), FIRST EPSS, NVD/CWE (public domain). Served live from the Stateward advisory database.