Listen to this Post
Thumbor is an open-source photo thumbnail service that provides on-demand image cropping, resizing, and filtering. To prevent Server-Side Request Forgery (SSRF) attacks, Thumbor implements an `ALLOWED_SOURCES` configuration setting that restricts which hostnames the HTTP loader is permitted to fetch images from.
The vulnerability exists in the `validate()` function within thumbor/loaders/http_loader.py. When `ALLOWED_SOURCES` contains plain-string entries (the overwhelmingly common configuration pattern used in real-world deployments and official documentation), these strings are passed directly to Python’s `re.match()` without any escaping.
Because the dot character (.) is treated as a wildcard in regular expressions—matching any single character except a newline—every dot in a domain name becomes a bypass vector. For example, a configuration containing `s.glbimg.com` will also match sXglbimgYcom, sAglbimg.com, and any other hostname that differs only at dot positions. The `re.match()` call anchors the pattern with `^` and `$` (e.g., ^s.glbimg.com$), but the unescaped dots still allow a wide range of hostnames to bypass the allowlist.
An attacker who can influence the image source URL passed to Thumbor can exploit this to fetch images from arbitrary internal or external hosts, completely defeating the primary SSRF defence that `ALLOWED_SOURCES` is intended to provide. The preconditions for exploitation are that `ALLOWED_SOURCES` contains at least one plain-string entry and that `ALLOW_UNSAFE_URL` is set to `True` (the default) or that the application forwards user input to a signed URL endpoint.
The fix is simple yet effective: apply `re.escape()` to plain-string patterns before compiling them, ensuring that dots and other regex metacharacters are matched literally. Users who require genuine regular-expression behaviour can still supply a compiled pattern (e.g., re.compile(r"s\.glbimg\.com")), which is handled by the existing `isinstance(pattern, Pattern)` branch and remains unaffected.
DailyCVE Form:
Platform: Thumbor
Version: < 7.8.0
Vulnerability : SSRF Bypass
Severity: Critical (CVSS 8.2)
date: 2026-07-31
Prediction: 2026-07-31
What Undercode Say:
Analytics of the vulnerability reveals the following key indicators:
Check Thumbor version thumbor --version Verify if ALLOWED_SOURCES contains plain strings grep -r "ALLOWED_SOURCES" /etc/thumbor.conf Test for vulnerable configuration python3 -c " import re pattern = r'^s.glbimg.com$' print(re.match(pattern, 'sXglbimgYcom')) Returns match if vulnerable "
The vulnerability affects all Thumbor instances prior to version 7.8.0 where `ALLOWED_SOURCES` is configured with plain strings. The official GitHub security advisory (GHSA-6×26-6r6f-m537) documents the issue, and the fix was merged in commit 68876715350c6c8f49c324e5515e64908830aed7.
Exploit:
Proof of concept demonstrating the bypass:
import re from thumbor.config import Config from thumbor.context import Context from thumbor.loaders import http_loader as loader config = Config() config.ALLOWED_SOURCES = ["s.glbimg.com"] Typical user configuration ctx = Context(None, config, None) These should be blocked but return True due to unescaped dots print(loader.validate(ctx, "http://sXglbimgYcom/secret.jpg")) True — Bypass print(loader.validate(ctx, "http://sAglbimg.com/secret.jpg")) True — Bypass Legitimate origin is correctly allowed print(loader.validate(ctx, "http://s.glbimg.com/logo.jpg")) True — Correct
The vulnerable code path in `thumbor/loaders/http_loader.py` before the fix:
for pattern in context.config.ALLOWED_SOURCES:
if isinstance(pattern, Pattern):
match = url
else:
pattern = f"^{pattern}$" Dots not escaped — act as regex wildcard
match = res.hostname
if re.match(pattern, match):
return True
Protection:
Immediate Remediation:
- Upgrade to Thumbor version 7.8.0 or later
- The fix applies `re.escape()` to plain-string patterns:
else: pattern = f"^{re.escape(pattern)}$" Dots and metacharacters are now literal match = res.hostname
Workarounds (if immediate upgrade is not possible):
- Replace plain-string entries with compiled regex patterns that explicitly escape dots:
import re ALLOWED_SOURCES = [re.compile(r"s.glbimg.com")]
- Restrict network access from the Thumbor instance to only permitted destinations using firewall rules or network segmentation
The `ALLOWED_SOURCES` docstring in `config.py` was also updated to document the two-mode behaviour explicitly.
Impact:
- SSRF Attacks: Attackers can fetch images from arbitrary internal or external hosts, bypassing the allowlist
- Data Exfiltration: Internal services (e.g., metadata endpoints, cloud instance metadata services) may be reachable and readable
- Network Scanning: The Thumbor instance can be used as a proxy to scan internal networks
- CVSS Score: 8.2 (High) — Network attack vector, low attack complexity, no privileges required, no user interaction, high confidentiality impact
- CWE: CWE-918 — Server-Side Request Forgery (SSRF)
- Affected Versions: All Thumbor releases prior to 7.8.0
🎯Let’s Practice Exploiting & Learn Patching For Free:
🎓 Live Courses & Certifications:
Join Undercode Academy for Verified Certifications
🚀 Request a Custom Project:
Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

