Executive Summary
An unauthenticated denial-of-service (DoS) vulnerability exists in Grav, a popular content management system. By requesting an image with oversized resize dimensions, an attacker can cause a significant increase in server memory and CPU usage, potentially leading to a denial-of-service condition. This vulnerability has been assigned CVE-2026-53653 and has a CVSS score of 8.7.
Technical Analysis
The vulnerability lies in the `Grav::fallbackUrl()` method (system/src/Grav/Common/Grav.php:800-804), which loops over every query parameter and calls methods on the `ImageMedium` class with comma-split values as arguments. Specifically, the `forceResize` method sets the output size to the attacker's values without any clamping against the source or ceiling. The `getgrav/image` GD adapter then calls `imagecreatetruecolor($w, $h)`, allocating a buffer outside PHP's `emalloc`, which is not capped by `memory_limit`.
How It Gets Exploited
An unauthenticated remote attacker can exploit this vulnerability by sending a crafted GET request to any page that serves an image with oversized resize dimensions. For example, requesting an image with the following URL: `/home/test.png?forceResize=20000,20000`. This request can cause a worker to consume several gigabytes of RAM and tens of seconds of CPU, potentially taking the host down.
Impact Assessment
Any Grav site that serves images is affected by this vulnerability, with no account, plugin, or non-default config required. The vulnerability has a CVSS score of 8.7, indicating a high severity level. An attacker can achieve an unauthenticated denial-of-service condition, potentially disrupting the availability of the affected site.
Recommended Actions
To mitigate this vulnerability, it is recommended to update Grav to a version that includes the fix, which clamps the request-derived dimensions before dispatch behind a configurable cap. Specifically, update `system/src/Grav/Common/Grav.php` with the following changes:
```diff
--- a/system/src/Grav/Common/Grav.php
+++ b/system/src/Grav/Common/Grav.php
@@ public function fallbackUrl($path)
foreach ($uri->query(null, true) as $action => $params) {
if (in_array($action, ImageMedium::$magic_actions, true)) {
- call_user_func_array([&$medium, $action], explode(',', $params));
+ $args = explode(',', $params);
+ $max = (int) $config->get('system.images.max_dimension', 8000);
+ if ($max > 0
+ && in_array($action, ['resize', 'forceResize', 'cropResize', 'cropZoom', 'zoomCrop', 'crop'], true)) {
+ foreach ($args as $a) {
+ if (is_numeric($a) && (int) $a > $max) {
+ return false; // reject oversized derivative request
+ }
+ }
+ }
+ call_user_func_array([&$medium, $action], $args);
}
}
```
Additionally, document `system.images.max_dimension` (default 8000) so operators can tune it. A total-pixel ceiling (`width * height`) is a stricter alternative.
Sources
- GitHub Security Advisories
- CVE-2026-53653