Answer in brief
CVE-2026-53503 records a High severity missing auth vulnerability in Thumbor convolution filter allows divide-by-zero in C extension leading to remote DoS. The source record does not mark it as known exploited. 1 affected package is mapped in the feed.
Answer in brief
CVE-2026-53503 records a High severity missing auth vulnerability in Thumbor convolution filter allows divide-by-zero in C extension leading to remote DoS. The source record does not mark it as known exploited. 1 affected package is mapped in the feed.
Update thumbor to 7.8.0 if you use the affected versions. Test the change in a non-production environment first.
Local check
hol-guard supply-chain scanMissing Auth describes the vulnerability class recorded for this advisory. The current record does not mark CVE-2026-53503 as known exploited; continue to monitor the source for status changes. The feed includes package mappings that can be checked against lockfiles and deployed manifests.
| Package | Affected range | Fixed version |
|---|---|---|
| thumborpip | <=7.7.7 | 7.8.0 |
Fixed versions are reported by the source feed; confirm compatibility before updating.
Reported by GitHub Security Advisories (ghsa).
CVE-2026-53503 records a High severity missing auth vulnerability in Thumbor convolution filter allows divide-by-zero in C extension leading to remote DoS. The source record does not mark it as known exploited. 1 affected package is mapped in the feed.
The source record does not mark it as known exploited.
Check lockfiles and deployed manifests for thumbor.
HOL Guard can help your team review package activity against supported protection paths.
Explore HOL GuardUpdate thumbor to 7.8.0 if you use the affected versions. Test the change in a non-production environment first.
Local check
hol-guard supply-chain scanMissing Auth describes the vulnerability class recorded for this advisory. The current record does not mark CVE-2026-53503 as known exploited; continue to monitor the source for status changes. The feed includes package mappings that can be checked against lockfiles and deployed manifests.
| Package | Affected range | Fixed version |
|---|---|---|
| thumborpip | <=7.7.7 | 7.8.0 |
Fixed versions are reported by the source feed; confirm compatibility before updating.
Reported by GitHub Security Advisories (ghsa).
CVE-2026-53503 records a High severity missing auth vulnerability in Thumbor convolution filter allows divide-by-zero in C extension leading to remote DoS. The source record does not mark it as known exploited. 1 affected package is mapped in the feed.
The source record does not mark it as known exploited.
Check lockfiles and deployed manifests for thumbor.
HOL Guard can help your team review package activity against supported protection paths.
Explore HOL Guard### Summary Thumbor's `filters:convolution(<matrix>, <columns>, <should_normalize>)` 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 x86_64 this reliably results in a fatal divide-by-zero trap (SIGFPE) and crashes the Thumbor process (confirmed on Linux x86_64 and macOS Intel x86_64), causing a remote denial of service. ### Details #### Root cause The Python filter accepts `columns=0`, and the native C extension uses `columns_count` as a divisor without validating it. 1) Python filter entry point allows `columns=0` (`thumbor/filters/convolution.py`): ```python @filter_method( r"(?:[-]?[\d]+\.?[\d]*[;])*(?:[-]?[\d]+\.?[\d]*)", BaseFilter.PositiveNumber, # accepts 0 BaseFilter.Boolean, ) async def convolution(self, matrix, columns, should_normalize=True): ... imgdata = _convolution.apply(..., matrix, columns, should_normalize) ``` `BaseFilter.PositiveNumber` matches `"0"` (`thumbor/filters/__init__.py`): ```python class BaseFilter: PositiveNumber = {"regex": r"[\d]+", "parse": int} # matches "0" PositiveNonZeroNumber = {"regex": r"[\d]*[1-9][\d]*", "parse": int} ``` 2) C extension divides/modulos by `columns_count` without a zero check (`thumbor/ext/filters/_convolution.c`): ```c kernel_size = PyTuple_Size(kernel_tuple); if ((kernel_size % columns_count != 0) || (kernel_size % 2 == 0) || ((kernel_size / columns_count) % 2) == 0) { // TODO: error, not a valid kernel return NULL; } ``` ### PoC #### Test environment - Linux x86_64 #### Preconditions - The `convolution` filter is enabled (it is enabled by default via `BUILTIN_FILTERS`). - Either: - `/unsafe/` URLs are allowed (`ALLOW_UNSAFE_URL=True`), OR - `/unsafe/` is disabled, and the attacker has a valid signed URL (i.e., the attacker is an authorized user/partner, or can obtain signed URLs from a trusted signing service). #### Example request (signed URL) `http://<host>:<port>/<url-sign>/400x400/filters:convolution(1;2;1;2;4;2;1;2;1,0,true)/example.jpg` #### Example request (/unsafe/) `http://<host>:<port>/unsafe/400x400/filters:convolution(1;2;1;2;4;2;1;2;1,0,true)/example.jpg` ### Impact - Remote Denial of Service via process crash (SIGFPE) on x86_64 (confirmed on Linux x86_64 and macOS Intel x86_64). - 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 is an authorized user/partner, or can obtain signed URLs from a trusted signing service) ### Suggested remediation - In the C extension (`thumbor/ext/filters/_convolution.c`): - Reject `columns_count <= 0` before any `%` or `/`. - In the Python filter (`thumbor/filters/convolution.py`): - Require `columns` to be non-zero (e.g., use `BaseFilter.PositiveNonZeroNumber`).
### Summary Thumbor's `filters:convolution(<matrix>, <columns>, <should_normalize>)` 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 x86_64 this reliably results in a fatal divide-by-zero trap (SIGFPE) and crashes the Thumbor process (confirmed on Linux x86_64 and macOS Intel x86_64), causing a remote denial of service. ### Details #### Root cause The Python filter accepts `columns=0`, and the native C extension uses `columns_count` as a divisor without validating it. 1) Python filter entry point allows `columns=0` (`thumbor/filters/convolution.py`): ```python @filter_method( r"(?:[-]?[\d]+\.?[\d]*[;])*(?:[-]?[\d]+\.?[\d]*)", BaseFilter.PositiveNumber, # accepts 0 BaseFilter.Boolean, ) async def convolution(self, matrix, columns, should_normalize=True): ... imgdata = _convolution.apply(..., matrix, columns, should_normalize) ``` `BaseFilter.PositiveNumber` matches `"0"` (`thumbor/filters/__init__.py`): ```python class BaseFilter: PositiveNumber = {"regex": r"[\d]+", "parse": int} # matches "0" PositiveNonZeroNumber = {"regex": r"[\d]*[1-9][\d]*", "parse": int} ``` 2) C extension divides/modulos by `columns_count` without a zero check (`thumbor/ext/filters/_convolution.c`): ```c kernel_size = PyTuple_Size(kernel_tuple); if ((kernel_size % columns_count != 0) || (kernel_size % 2 == 0) || ((kernel_size / columns_count) % 2) == 0) { // TODO: error, not a valid kernel return NULL; } ``` ### PoC #### Test environment - Linux x86_64 #### Preconditions - The `convolution` filter is enabled (it is enabled by default via `BUILTIN_FILTERS`). - Either: - `/unsafe/` URLs are allowed (`ALLOW_UNSAFE_URL=True`), OR - `/unsafe/` is disabled, and the attacker has a valid signed URL (i.e., the attacker is an authorized user/partner, or can obtain signed URLs from a trusted signing service). #### Example request (signed URL) `http://<host>:<port>/<url-sign>/400x400/filters:convolution(1;2;1;2;4;2;1;2;1,0,true)/example.jpg` #### Example request (/unsafe/) `http://<host>:<port>/unsafe/400x400/filters:convolution(1;2;1;2;4;2;1;2;1,0,true)/example.jpg` ### Impact - Remote Denial of Service via process crash (SIGFPE) on x86_64 (confirmed on Linux x86_64 and macOS Intel x86_64). - 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 is an authorized user/partner, or can obtain signed URLs from a trusted signing service) ### Suggested remediation - In the C extension (`thumbor/ext/filters/_convolution.c`): - Reject `columns_count <= 0` before any `%` or `/`. - In the Python filter (`thumbor/filters/convolution.py`): - Require `columns` to be non-zero (e.g., use `BaseFilter.PositiveNonZeroNumber`).