CVE-2026-54002
Kirby: Cross-site scripting (XSS) from incomplete HTML/XML sanitization in `Dom::sanitize()`
Kirby is an open-source content management system. Prior to 4.9.4 and 5.4.4, Kirby sites and plugins that use the writer or list fields or call Dom::sanitize(), Sane::sanitize(), Sane::Html::sanitize(), Sane::Svg::sanitize(), Sane::Xml::sanitize(), Sane::sanitizeFile(), or file sanitizeContents() with untrusted input allow malicious markup injected as children of an unknown HTML or XML tag to pass through Dom::sanitize() without being correctly sanitized, causing stored cross-site scripting. This issue is fixed in versions 4.9.4 and 5.4.4.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- Low
- User interaction
- Passive
What an attacker can affect
- Confidentiality
- High
- Integrity
- High
- Availability
- None
Exploit likelihood
What each source reports
CVE List Score used
8.5
Kirby: Cross-site scripting (XSS) from incomplete HTML/XML sanitization in `Dom::sanitize()`
Kirby is an open-source content management system. Prior to 4.9.4 and 5.4.4, Kirby sites and plugins that use the writer or list fields or call Dom::sanitize(), Sane::sanitize(), Sane::Html::sanitize(), Sane::Svg::sanitize(), Sane::Xml::sanitize(), Sane::sanitizeFile(), or file sanitizeContents() with untrusted input allow malicious markup injected as children of an unknown HTML or XML tag to pass through Dom::sanitize() without being correctly sanitized, causing stored cross-site scripting. This issue is fixed in versions 4.9.4 and 5.4.4.
- Record
CVE-2026-54002- CVSS 4.0
- 8.5 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:P/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N - Weakness
- CWE-79, CWE-87
- Updated
- 2026-11-02
EUVDEUVD-2026-42687
8.5
Kirby is an open-source content management system. Prior to 4.9.4 and 5.4.4, Kirby sites and plugins that use the writer or list fields or call Dom::sanitize(), Sane::sanitize(), Sane::Html::sanitize(), Sane::Svg::sanitize(), Sane::Xml::sanitize(), Sane::sanitizeFile(), or file sanitizeContents() with untrusted input allow malicious markup injected as children of an unknown HTML or XML tag to pass through Dom::sanitize() without being correctly sanitized, causing stored cross-site scripting. This issue is fixed in versions 4.9.4 and 5.4.4.
- Record
EUVD-2026-42687- CVSS 4.0
- 8.5 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:P/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-wr9h-4r83-f4v6
8.5
Kirby: Cross-site scripting (XSS) from incomplete HTML/XML sanitization in `Dom::sanitize()`
TL;DR
This vulnerability affects Kirby sites and plugins that use the writer or list fields or that use $dom->sanitize(), Sane::sanitize(), Sane\Html::sanitize(), Sane\Svg::sanitize(), Sane\Xml::sanitize(), Sane::sanitizeFile() or $file->sanitizeContents() with untrusted input.
It was possible to inject malicious markup as children of an unknown HTML/XML tag, which would then be passed through Dom::sanitize() without being correctly sanitized according to the provided sanitization rules, causing a cross-site scripting (XSS) risk.
This vulnerability is of high severity for affected sites.
The default file upload protection is not affected, so sites that only validate uploaded files are not exposed to this vulnerability. The vulnerability can only be exploited by authenticated users.
Introduction
Cross-site scripting (XSS) is a type of vulnerability that allows executing any kind of JavaScript code inside the site frontend or Panel session of the same or other users. In the Panel, a harmful script can, for example, trigger requests to Kirby's API with the permissions of the victim.
In a stored XSS attack, the malicious payload is saved into the content data and has the potential to affect other users or site visitors.
Such vulnerabilities are critical if you might have potential attackers in your group of authenticated Panel users. They can escalate their privileges if they get access to the Panel session of an admin user. Depending on your site, other JavaScript-powered attacks are possible.
A specific class of stored XSS is auto-firing, meaning the maliciously injected JavaScript code is executed by the browser when the page loads without the victim having to perform a specific action.
Affected components
The Dom::sanitize() method allows removing unwanted or malicious elements or attributes from DOM documents (which includes HTML, SVG or arbitrary XML data). Sanitized content is supposed to be protected against cross-site scripting (XSS) attacks by removing their impact from untrusted content input.
Dom::sanitize() internally checks all nodes and attributes of the DOM document. It removes nodes, attributes, processing instructions, doctypes and namespaces that are not allowed according to the provided configuration. Nodes with tags that have been explicitly blocklisted are removed together with their children. Nodes with explicitly allowlisted tags are kept. If a tag is neither allowlisted nor blocklisted, nodes with that tag are unwrapped by Dom::unwrap() (meaning the children are kept).
Dom::sanitize() is used in the following components:
- The
writerfield sanitizes all entered content on the backend before it is saved to the content file. - The
listfield performs the same sanitization as thewriterfield since Kirby 5.4.1 (and in backported versions since Kirby 4.9.1). - The
Kirby\Saneclass package includes higher-level classesSane\Html,Sane\SvgandSane\Xmlthat all rely on DOM sanitization. - These classes are in turn also used by
Sane::sanitizeFile()and$file->sanitizeContents(). - Any of the mentioned methods could also be used in site or plugin code, for example in a
file.create:beforehook that cleans uploaded SVG/HTML files.
Only the sanitization path (returning a cleaned document) is affected. The validation path is not affected by this vulnerability. Kirby's default upload protection performs validation, so malicious SVG or HTML uploads continue to be rejected.
Impact
In affected releases, Dom::sanitize() did not sanitize nodes that had been unwrapped from their parent node. The affected child nodes would be copied into the resulting sanitized document without being sanitized.
An authenticated Panel user who can edit a writer or list field can store markup that survives sanitization and executes as JavaScript when the content is rendered, both in the Panel and on the site frontend. This allows a…
- Record
GHSA-wr9h-4r83-f4v6- CVSS 4.0
- 8.5 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:P/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N - Weakness
- CWE-79, CWE-87
- Updated
- 2026-11-02
NVD
8.5
Kirby is an open-source content management system. Prior to 4.9.4 and 5.4.4, Kirby sites and plugins that use the writer or list fields or call Dom::sanitize(), Sane::sanitize(), Sane::Html::sanitize(), Sane::Svg::sanitize(), Sane::Xml::sanitize(), Sane::sanitizeFile(), or file sanitizeContents() with untrusted input allow malicious markup injected as children of an unknown HTML or XML tag to pass through Dom::sanitize() without being correctly sanitized, causing stored cross-site scripting. This issue is fixed in versions 4.9.4 and 5.4.4.
- Record
CVE-2026-54002- CVSS 4.0
- 8.5 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:P/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - Weakness
- CWE-79, CWE-87
- Updated
- 2026-11-02
OSV
8.5
Kirby: Cross-site scripting (XSS) from incomplete HTML/XML sanitization in `Dom::sanitize()`
Kirby is an open-source content management system. Prior to 4.9.4 and 5.4.4, Kirby sites and plugins that use the writer or list fields or call Dom::sanitize(), Sane::sanitize(), Sane::Html::sanitize(), Sane::Svg::sanitize(), Sane::Xml::sanitize(), Sane::sanitizeFile(), or file sanitizeContents() with untrusted input allow malicious markup injected as children of an unknown HTML or XML tag to pass through Dom::sanitize() without being correctly sanitized, causing stored cross-site scripting. This issue is fixed in versions 4.9.4 and 5.4.4.
- Record
CVE-2026-54002- CVSS 4.0
- 8.5 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:P/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N - Weakness
- CWE-79, CWE-87
- Updated
- 2026-11-02
OSVGHSA-wr9h-4r83-f4v6
8.5
Kirby: Cross-site scripting (XSS) from incomplete HTML/XML sanitization in `Dom::sanitize()`
TL;DR
This vulnerability affects Kirby sites and plugins that use the writer or list fields or that use $dom->sanitize(), Sane::sanitize(), Sane\Html::sanitize(), Sane\Svg::sanitize(), Sane\Xml::sanitize(), Sane::sanitizeFile() or $file->sanitizeContents() with untrusted input.
It was possible to inject malicious markup as children of an unknown HTML/XML tag, which would then be passed through Dom::sanitize() without being correctly sanitized according to the provided sanitization rules, causing a cross-site scripting (XSS) risk.
This vulnerability is of high severity for affected sites.
The default file upload protection is not affected, so sites that only validate uploaded files are not exposed to this vulnerability. The vulnerability can only be exploited by authenticated users.
Introduction
Cross-site scripting (XSS) is a type of vulnerability that allows executing any kind of JavaScript code inside the site frontend or Panel session of the same or other users. In the Panel, a harmful script can, for example, trigger requests to Kirby's API with the permissions of the victim.
In a stored XSS attack, the malicious payload is saved into the content data and has the potential to affect other users or site visitors.
Such vulnerabilities are critical if you might have potential attackers in your group of authenticated Panel users. They can escalate their privileges if they get access to the Panel session of an admin user. Depending on your site, other JavaScript-powered attacks are possible.
A specific class of stored XSS is auto-firing, meaning the maliciously injected JavaScript code is executed by the browser when the page loads without the victim having to perform a specific action.
Affected components
The Dom::sanitize() method allows removing unwanted or malicious elements or attributes from DOM documents (which includes HTML, SVG or arbitrary XML data). Sanitized content is supposed to be protected against cross-site scripting (XSS) attacks by removing their impact from untrusted content input.
Dom::sanitize() internally checks all nodes and attributes of the DOM document. It removes nodes, attributes, processing instructions, doctypes and namespaces that are not allowed according to the provided configuration. Nodes with tags that have been explicitly blocklisted are removed together with their children. Nodes with explicitly allowlisted tags are kept. If a tag is neither allowlisted nor blocklisted, nodes with that tag are unwrapped by Dom::unwrap() (meaning the children are kept).
Dom::sanitize() is used in the following components:
- The
writerfield sanitizes all entered content on the backend before it is saved to the content file. - The
listfield performs the same sanitization as thewriterfield since Kirby 5.4.1 (and in backported versions since Kirby 4.9.1). - The
Kirby\Saneclass package includes higher-level classesSane\Html,Sane\SvgandSane\Xmlthat all rely on DOM sanitization. - These classes are in turn also used by
Sane::sanitizeFile()and$file->sanitizeContents(). - Any of the mentioned methods could also be used in site or plugin code, for example in a
file.create:beforehook that cleans uploaded SVG/HTML files.
Only the sanitization path (returning a cleaned document) is affected. The validation path is not affected by this vulnerability. Kirby's default upload protection performs validation, so malicious SVG or HTML uploads continue to be rejected.
Impact
In affected releases, Dom::sanitize() did not sanitize nodes that had been unwrapped from their parent node. The affected child nodes would be copied into the resulting sanitized document without being sanitized.
An authenticated Panel user who can edit a writer or list field can store markup that survives sanitization and executes as JavaScript when the content is rendered, both in the Panel and on the site frontend. This allows a…
- Record
GHSA-wr9h-4r83-f4v6- CVSS 4.0
- 8.5 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:P/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N - Weakness
- CWE-79, CWE-87
- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
getkirby/cmsPackagist |
through 4.9.3 | 4.9.4 |
getkirby/cmsPackagist |
5.0.0-alpha.1 to 5.4.3 | 5.4.4 |
getkirby/cmsPackagist |
before 4.9.4, plus listed versions 3.0.03.0.13.0.1-rc.13.0.23.0.2-rc.1 Show 45 moreShow less3.0.33.0.3-rc.13.0.3-rc.23.0.3-rc.33.1.03.1.0-rc.13.1.13.1.23.1.2-rc.13.1.33.1.3-rc.13.1.43.1.4-rc.13.10.03.10.0.13.10.13.10.1.13.10.1.23.2.03.2.0-rc.13.2.0-rc.23.2.0-rc.33.2.0-rc.43.2.13.2.1-rc.13.2.23.2.33.2.3-rc.13.2.43.2.4-rc.13.2.53.2.5-rc.13.2.5-rc.23.3.03.3.0-rc.13.3.0-rc.23.3.0-rc.33.3.0-rc.43.3.0-rc.53.3.13.3.1-rc.13.3.23.3.2-rc.13.3.33.3.3-rc.1 |
4.9.4 |
getkirby/cmsPackagist |
5.0.0-alpha.1 up to 5.4.4, plus listed versions 5.0.05.0.0-alpha.25.0.0-alpha.35.0.0-alpha.45.0.0-beta.1 Show 35 moreShow less5.0.0-beta.25.0.0-beta.35.0.0-beta.45.0.0-beta.55.0.0-beta.65.0.0-rc.15.0.0-rc.25.0.0-rc.35.0.0-rc.45.0.0-rc.55.0.0-rc.65.0.15.0.25.0.35.0.45.1.05.1.0-rc.15.1.15.1.25.1.35.1.45.2.05.2.0-rc.15.2.15.2.25.2.35.3.05.3.0-rc.15.3.15.3.25.3.35.4.05.4.15.4.25.4.3 |
5.4.4 |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-54002 is a high vulnerability (CVSS 8.5) in Getkirby Kirby, published June 18, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.55%, the 46th percentile. Fixed in getkirby/cms 4.9.4.
References
github.com/getkirby/kirby/security/advisories/GHSA-wr9h-4r83-f4v6
github.com/getkirby/kirby/commit/0f0437b5128c910103cbc78fc34d94b2a3faef4c
github.com/getkirby/kirby/commit/7ad76cf9c7387462828e6ebfc8404e31b37829e9
github.com/getkirby/kirby/commit/9ec1873864441dbc06479ef7823da348ec7f2700
github.com/getkirby/kirby/commit/bb2562e16c754493a403b8df84c9883108871e4c
github.com/getkirby/kirby/releases/tag/4.9.4
Left out here: 187 versions and the rest of 2 source descriptions. The JSON record has them.