Attack ChainAIDerived
Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain
-
AccessRegister low-privileged Discourse account
-
DeliverySet crafted display name with script markup
-
ExploitTrigger a post action rendered in activity stream
-
ExecutionVictim views affected user activity stream
-
ImpactAttacker script executes in victim browser origin
Vulnerability Assessment
| Weakness |
CWE
OWASP Top 10:2025
A05:2025 - Injection
ASVS 5.0
V1 - Encoding and Sanitization Output encoding, context-aware escaping
MITRE ATT&CK
2 techniques across 2 tactics: Initial Access, Execution The technique list with ATT&CK links and the kill-chain view is part of the Basic plan and up. |
| Exploitation Conditions | Requires an authenticated Discourse account (PR:L) capable of setting a display/user name - the attacker must be able to choose a crafted name that gets interpolated into a post action description. Exploitation further requires a victim to view the affected user-activity stream (UI:R), so it is not fully automatable and depends on the attacker's actions surfacing in streams other users browse. Affects default configurations of Discourse prior to 2026.7.0 (no non-default feature toggle is named in the description); the flaw is in the standard post-action-description component, so any instance allowing user-chosen display names is exposed until upgraded. |
| Impact | This is a stored/persistent XSS (CWE-79) in Discourse rated 5.4 (Medium) by the vendor, with the CVSS vector CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N. The signals are mutually consistent and modest: the network attack vector and low complexity are offset by PR:L (an attacker must hold an account able to set a crafted display name) and UI:R (a victim must view the affected user-activity stream). The scope change (S:C) correctly reflects that injected script executes in a different user's browser session, but confidentiality and integrity impact are only Low and availability is unaffected. No EPSS score, no CISA KEV listing, and no standalone weaponized exploit are present in the input, so there is no evidence of active exploitation - the fix commit does ship a regression test demonstrating the payload ( |
| Exploit ScenarioDerived | An attacker registers or uses a low-privileged Discourse account and sets a display name containing HTML/script markup (e.g. an img tag with an onerror handler). When that user performs a post action (like, invite, flag) that is rendered in another user's activity stream, the unescaped name is interpolated into HTML passed to trustHTML and executes in the victim's browser. No standalone public exploit is published, but the fix commit includes a regression test that demonstrates the exact payload, making reproduction straightforward. |
Get an e-mail when this CVE is exploited, patched or re-scored. Free account.
Alert meAnalysisAIv1 – Sep 21, 2026
Stored cross-site scripting in Discourse before 2026.7.0 allows an authenticated user who can set a custom display name to persist markup that is later rendered in post action descriptions, so that any other user browsing the affected activity streams runs attacker-controlled script in their browser. The vendor scores it 5.4 (Medium) with the vector CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N, reflecting an authenticated attacker (PR:L) and a required victim interaction (UI:R), with scope change because the script executes in other users' sessions against the Discourse origin. The vendor-released fix is version 2026.7.0; there is no public exploit code identified at time of analysis and no CISA KEV listing.
RemediationAI
Upgrade to Discourse 2026.7.0 or later, which is the exact vendor-released fix version (release tag https://github.com/discourse/discourse/releases/tag/v2026.7.0, advisory https://github.com/discourse/discourse/security/advisories/GHSA-x6mf-p7cg-69rw); operators who maintain a fork or cannot move to the release line should backport commit dd786594ddd088657a7e6f9fefba5bd889965fe4, which adds escapeExpression() for the actor name and encodeURIComponent() for the link path. Until the upgrade is applied, the most direct compensating control is to remove or tightly restrict user-controlled display names - for example require staff approval of name changes, disable self-service name changes for non-staff, or freeze existing names - with the trade-off of reduced user self-expression and added moderation workload. A strict Content-Security-Policy that disallows inline script and untrusted script sources will neutralize the <img onerror> style payloads demonstrated in the upstream test, but Discourse may rely on inline script or trusted CDNs for themes, oneboxes, and plugins, so CSP changes should be tested in staging as they can break site customizations. Deploying a temporary, targeted hotfix in post-action-description.gjs is also viable and lower-risk than CSP changes if your deployment pipeline supports patches; note that no KEV listing or public exploit code exists, so the practical urgency is driven by the stored nature of the payload and the breadth of the activity-stream view surface, not by observed active exploitation.
Affected VersionsENISA
Affected Packages
Source: OSV (Open Source Vulnerabilities)
Affects your stack
Affects 1 package in euvd
Checking this CVE against your own stacks and servers is part of the Basic plan and up.
Technical ContextAI · show details
The flaw is CWE-79 (Improper Neutralization of Input During Web Page Generation, i.e. cross-site scripting), located in Discourse's front-end Ember/Glimmer component frontend/discourse/app/components/post-action-description.gjs. The actionDescriptionHtml() helper builds an HTML string for post action descriptions and hands it to Discourse's trustHTML mechanism, which marks the string as safe and bypasses the framework's normal HTML escaping. The actor's display/user name was interpolated into that string both as visible anchor text and into the href of the generated <a class="mention"> or <a class="mention-group"> link without sanitization, so a name such as <img src=x onerror="alert(1)"> became live DOM when the description was rendered. The upstream commit dd786594ddd088657a7e6f9fefba5bd889965fe4 corrects this by wrapping the name with escapeExpression() from discourse/lib/utilities for the display text and applying encodeURIComponent() for the URL segment, and adds an integration test that renders the component with an HTML payload name and asserts that no element is created and the name is shown as literal text. Because the rendered context is a trusted-HTML sink, the missing escaping is the entire root cause; the CPE cpe:2.3:a:discourse:discourse:*:*:*:*:*:*:*:* covers all Discourse releases before the fixed tag.
Know when Discourse gets its next vulnerability
- Watch products and get an email when something new is published
- Check this CVE against your own stack and servers
- Exploit and PoC references, threat intelligence from 22 sources
No credit card · 7-day full trial
Severity by source
AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N
Attacker needs a low-privileged account to set the crafted name (PR:L) and a victim must view the stream (UI:R); script runs in the victim's origin (S:C) with limited C/I impact and no availability effect.
Primary rating from Vendor (GitHub_M).
CVSS VectorVendor: GitHub_M
Lifecycle Timeline
1DescriptionCVE.org
Discourse is an open-source discussion platform. Prior to 2026.7.0, the post action component failed to escape user-controlled display names before interpolating them into an HTML string passed to trustHTML. A user who could choose a crafted display name could persist markup in post action descriptions. Viewing the affected user activity streams could execute attacker-controlled script in another user's browser. This issue is fixed in version 2026.7.0.
Threat Intelligence Overview
How this decision was reached
The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.
What every action level means
SSVC AssessmentENISA
Priority Score
Attack Technique
Cross-Site Scripting occurs when an application accepts untrusted data and sends it to a web browser without proper validation or encoding.
Discourse versions prior to 3.5.0.beta6 contain a reflected cross-site scripting (XSS) vulnerability in social login fun
discourse-bbcode is the official BBCode plugin for Discourse. Rated critical severity (CVSS 9.8), this vulnerability is
Unauthorized information disclosure in Discourse discussion platform versions prior to 2026.3.0-latest.1, 2026.2.1, and
Discourse is an open source platform for community discussion. Rated high severity (CVSS 8.2), this vulnerability is rem
Discourse versions prior to 2025.12.2, 2026.1.1, and 2026.2.0 contain an insecure direct object reference (IDOR) in the
In Discourse 2.7.0 through beta1, a rate-limit bypass leads to a bypass of the 2FA requirement for certain forms. Rated
Unauthenticated attackers can submit forged webhook payloads to multiple email provider integrations in Discourse versio
Discourse is an open-source discussion platform. Rated medium severity (CVSS 6.5), this vulnerability is remotely exploi
Discourse is an open source platform for community discussion. Rated medium severity (CVSS 5.9), this vulnerability is r
Discourse versions prior to 3.4.4 (stable), 3.5.0.beta5 (beta), and 3.5.0.beta6-dev (tests-passed) contain a critical vu
Discourse is an open source platform for community discussion. Rated critical severity (CVSS 9.8), this vulnerability is
Discourse Patreon enables syncronization between Discourse Groups and Patreon rewards. Rated critical severity (CVSS 9.8
EUVD-2026-84181
NVD
CVE.org
EPSS
Vulnrichment
GitHub
Exploit-DB