Every CVE Search/ Get API key

CVE-2026-55890

Grav: Stored CSS injection via Markdown image ?style=… reaches MediaObjectTrait::style()

4.8 MediumFix available

Grav is a file-based Web platform. Prior to 2.0.0-rc.9, Grav's incomplete fix for stored XSS through the Markdown media attribute action (CVE-2026-42841) leaves the sibling MediaObjectTrait::style method reachable through the same Markdown excerpt-action pipeline, allowing an editor to save Markdown image style parameters that are written into the rendered img style attribute without sanitization. This issue is fixed in version 2.0.0-rc.9.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
High
User interaction
Required

What an attacker can affect

Confidentiality
Low
Integrity
Low
Availability
None

Exploit likelihood

0.50%Up 0.3 points since Jul 11, 2026
90%50%10%1%

What each source reports

CVE List Score used 4.8

Grav: Stored CSS injection via Markdown image ?style=… reaches MediaObjectTrait::style()

Grav is a file-based Web platform. Prior to 2.0.0-rc.9, Grav's incomplete fix for stored XSS through the Markdown media attribute action (CVE-2026-42841) leaves the sibling MediaObjectTrait::style method reachable through the same Markdown excerpt-action pipeline, allowing an editor to save Markdown image style parameters that are written into the rendered img style attribute without sanitization. This issue is fixed in version 2.0.0-rc.9.

Record
CVE-2026-55890
CVSS 3.1
4.8 MediumCVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:C/C:L/I:L/A:N
Weakness
CWE-79
Updated
2026-11-02
EUVDEUVD-2026-42946 4.8

Grav is a file-based Web platform. Prior to 2.0.0-rc.9, Grav's incomplete fix for stored XSS through the Markdown media attribute action (CVE-2026-42841) leaves the sibling MediaObjectTrait::style method reachable through the same Markdown excerpt-action pipeline, allowing an editor to save Markdown image style parameters that are written into the rendered img style attribute without sanitization. This issue is fixed in version 2.0.0-rc.9.

Record
EUVD-2026-42946
CVSS 3.1
4.8 MediumCVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:C/C:L/I:L/A:N
Updated
2026-11-02
GitHub AdvisoriesGHSA-pmf8-g7c8-7v54 4.8

Grav: Stored CSS injection via Markdown image ?style=… reaches MediaObjectTrait::style() — incomplete patch of GHSA-r7fx-8g49-7hhr

Summary

The fix for GHSA-r7fx-8g49-7hhr / CVE-2026-42841 (Stored XSS via Markdown media attribute() action) is incomplete. The maintainer patched MediaObjectTrait::attribute() to deny dangerous attribute names (event handlers, style, xmlns, srcdoc, formaction) but the sibling MediaObjectTrait::style() method is reachable through the same Markdown excerpt-action pipeline and writes editor-controlled strings straight into the rendered <img style="…"> attribute with no sanitization.

Any user with admin.pages permission (e.g. an editor) can save Markdown like:

![logo](image.png?style=position:fixed;top:0;left:0;width:100vw;height:100vh;background:white;z-index:9999)

which renders to a stored-CSS payload that any higher-privileged viewer (administrator, super-admin, reviewer) loads in their authenticated session. Same trust boundary, same victim, same attacker, same Markdown input vector as the patched GHSA-r7fx-8g49-7hhr issue — the fix simply patched the attribute() entry point and missed the style() sibling.

Affected versions

Vulnerable at HEAD across every currently-shipping branch (verified 2026-06-15):

| Branch / tag | MediaObjectTrait::style() | |---|---| | develop (f4c0f42) | unpatched | | 2.0 (96e1d2d) | unpatched | | 2.0.0-rc.8 (latest 2.0 RC tag) | unpatched | | 1.7.52 (latest 1.7 stable) | unpatched |

Per SECURITY.md, this advisory targets the 2.0 line (publisher-level exploit, not eligible for 1.7 backport per the project's stated policy).

Trust boundary

Per the project's SECURITY.md:

A vulnerability is when an actor can escape the trust scope of their role: a publisher whose stored content compromises an admin session, an unauthenticated visitor who reaches a privileged sink, an account at any tier that gains capabilities it was not granted.

An editor authoring Markdown is operating within their role. A higher-privilege admin loading that editor's page in their authenticated session and getting attacker-controlled CSS painted into their browser is across the trust boundary — the same framing that was accepted for GHSA-r7fx-8g49-7hhr (MODERATE) and GHSA-c2q3-p4jr-c55f (MODERATE).

Details

Original GHSA-r7fx-8g49-7hhr fix (commit 5a12f9be8, 2026-04-23)

public function attribute($attribute = null, $value = '')
{
    if (empty($attribute) || !is_string($attribute)) {
        return $this;
    }
    if (!self::isSafeAttributeName($attribute)) {
        return $this;
    }
    $this->attributes[$attribute] = $value;
    return $this;
}

private static function isSafeAttributeName(string $name): bool
{
    if (!preg_match('/^[A-Za-z][A-Za-z0-9_:.\-]*$/', $name)) {
        return false;
    }
    $lower = strtolower($name);
    if (str_starts_with($lower, 'on')) {        // event handlers
        return false;
    }
    $denylist = ['style', 'xmlns', 'srcdoc', 'formaction'];
    return !in_array($lower, $denylist, true);
}

style is the second-named entry on the denylist — the maintainer explicitly recognised that editor-supplied style was dangerous when arriving via the attribute() action. The fix simply didn't reach the parallel sink.

The unpatched sibling: MediaObjectTrait::style() (line 519)

/**
 * Allows to add an inline style attribute from Markdown or Twig
 * Example: ![Example](myimg.png?style=float:left)
 */
public function style($style)
{
    $this->styleAttributes[] = rtrim($style, ';') . ';';
    return $this;
}

The function is unchanged before, during, and after the GHSA-r7fx-8g49-7hhr fix. The PHPDoc on the very next line names the Markdown invocation form (?style=…). The rtrim is for clean concatenation, not security.

$styleAttributes is concatenated and assigned to attributes['style'] in parsedownElement() (lines 242–251):

$style = '';
foreach ($this->styleAttributes as $key => $value) {
    if (is_numeric($key)) {        //…
Record
GHSA-pmf8-g7c8-7v54
CVSS 3.1
4.8 MediumCVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:C/C:L/I:L/A:N
Weakness
CWE-79
Updated
2026-11-02
NVD 4.8

Grav is a file-based Web platform. Prior to 2.0.0-rc.9, Grav's incomplete fix for stored XSS through the Markdown media attribute action (CVE-2026-42841) leaves the sibling MediaObjectTrait::style method reachable through the same Markdown excerpt-action pipeline, allowing an editor to save Markdown image style parameters that are written into the rendered img style attribute without sanitization. This issue is fixed in version 2.0.0-rc.9.

Record
CVE-2026-55890
CVSS 3.1
4.8 MediumCVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:C/C:L/I:L/A:N
Weakness
CWE-79
Updated
2026-11-02
OSV 4.8

Grav: Stored CSS injection via Markdown image ?style=… reaches MediaObjectTrait::style()

Grav is a file-based Web platform. Prior to 2.0.0-rc.9, Grav's incomplete fix for stored XSS through the Markdown media attribute action (CVE-2026-42841) leaves the sibling MediaObjectTrait::style method reachable through the same Markdown excerpt-action pipeline, allowing an editor to save Markdown image style parameters that are written into the rendered img style attribute without sanitization. This issue is fixed in version 2.0.0-rc.9.

Record
CVE-2026-55890
CVSS 3.1
4.8 MediumCVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:C/C:L/I:L/A:N
Weakness
CWE-79
Updated
2026-11-02
OSVGHSA-pmf8-g7c8-7v54 4.8

Grav: Stored CSS injection via Markdown image ?style=… reaches MediaObjectTrait::style() — incomplete patch of GHSA-r7fx-8g49-7hhr

Summary

The fix for GHSA-r7fx-8g49-7hhr / CVE-2026-42841 (Stored XSS via Markdown media attribute() action) is incomplete. The maintainer patched MediaObjectTrait::attribute() to deny dangerous attribute names (event handlers, style, xmlns, srcdoc, formaction) but the sibling MediaObjectTrait::style() method is reachable through the same Markdown excerpt-action pipeline and writes editor-controlled strings straight into the rendered <img style="…"> attribute with no sanitization.

Any user with admin.pages permission (e.g. an editor) can save Markdown like:

![logo](image.png?style=position:fixed;top:0;left:0;width:100vw;height:100vh;background:white;z-index:9999)

which renders to a stored-CSS payload that any higher-privileged viewer (administrator, super-admin, reviewer) loads in their authenticated session. Same trust boundary, same victim, same attacker, same Markdown input vector as the patched GHSA-r7fx-8g49-7hhr issue — the fix simply patched the attribute() entry point and missed the style() sibling.

Affected versions

Vulnerable at HEAD across every currently-shipping branch (verified 2026-06-15):

| Branch / tag | MediaObjectTrait::style() | |---|---| | develop (f4c0f42) | unpatched | | 2.0 (96e1d2d) | unpatched | | 2.0.0-rc.8 (latest 2.0 RC tag) | unpatched | | 1.7.52 (latest 1.7 stable) | unpatched |

Per SECURITY.md, this advisory targets the 2.0 line (publisher-level exploit, not eligible for 1.7 backport per the project's stated policy).

Trust boundary

Per the project's SECURITY.md:

A vulnerability is when an actor can escape the trust scope of their role: a publisher whose stored content compromises an admin session, an unauthenticated visitor who reaches a privileged sink, an account at any tier that gains capabilities it was not granted.

An editor authoring Markdown is operating within their role. A higher-privilege admin loading that editor's page in their authenticated session and getting attacker-controlled CSS painted into their browser is across the trust boundary — the same framing that was accepted for GHSA-r7fx-8g49-7hhr (MODERATE) and GHSA-c2q3-p4jr-c55f (MODERATE).

Details

Original GHSA-r7fx-8g49-7hhr fix (commit 5a12f9be8, 2026-04-23)

public function attribute($attribute = null, $value = '')
{
    if (empty($attribute) || !is_string($attribute)) {
        return $this;
    }
    if (!self::isSafeAttributeName($attribute)) {
        return $this;
    }
    $this->attributes[$attribute] = $value;
    return $this;
}

private static function isSafeAttributeName(string $name): bool
{
    if (!preg_match('/^[A-Za-z][A-Za-z0-9_:.\-]*$/', $name)) {
        return false;
    }
    $lower = strtolower($name);
    if (str_starts_with($lower, 'on')) {        // event handlers
        return false;
    }
    $denylist = ['style', 'xmlns', 'srcdoc', 'formaction'];
    return !in_array($lower, $denylist, true);
}

style is the second-named entry on the denylist — the maintainer explicitly recognised that editor-supplied style was dangerous when arriving via the attribute() action. The fix simply didn't reach the parallel sink.

The unpatched sibling: MediaObjectTrait::style() (line 519)

/**
 * Allows to add an inline style attribute from Markdown or Twig
 * Example: ![Example](myimg.png?style=float:left)
 */
public function style($style)
{
    $this->styleAttributes[] = rtrim($style, ';') . ';';
    return $this;
}

The function is unchanged before, during, and after the GHSA-r7fx-8g49-7hhr fix. The PHPDoc on the very next line names the Markdown invocation form (?style=…). The rtrim is for clean concatenation, not security.

$styleAttributes is concatenated and assigned to attributes['style'] in parsedownElement() (lines 242–251):

$style = '';
foreach ($this->styleAttributes as $key => $value) {
    if (is_numeric($key)) {        //…
Record
GHSA-pmf8-g7c8-7v54
CVSS 3.1
4.8 MediumCVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:C/C:L/I:L/A:N
Weakness
CWE-79
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
getgrav/grav
Packagist
through 2.0.0-rc.8
2.0.0-rc.9
getgrav/grav
Packagist
before 2.0.0-rc.9, plus listed versions
0.8.00.9.00.9.10.9.100.9.11
Show 45 moreShow less
0.9.120.9.130.9.140.9.150.9.160.9.170.9.180.9.190.9.20.9.200.9.210.9.220.9.230.9.240.9.250.9.260.9.270.9.280.9.290.9.30.9.300.9.310.9.320.9.330.9.340.9.350.9.360.9.370.9.380.9.390.9.40.9.400.9.410.9.420.9.430.9.440.9.450.9.50.9.60.9.70.9.80.9.91.0.01.0.0-rc.11.0.0-rc.2
2.0.0-rc.9

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-55890 is a medium vulnerability (CVSS 4.8) in Getgrav Grav, published June 18, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.50%, the 43rd percentile. Fixed in getgrav/grav 2.0.0-rc.9.

References

This page doesn't list everything

Left out here: 282 versions and the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open