CVE-2026-91121
Executive Summary
CVE-2026-91121 is a trusted-HTML injection vulnerability in Discourse, an open-source discussion platform, where attacker-controlled upload filenames referenced within chat message excerpts were rendered as unescaped HTML. Any authenticated user capable of uploading a file and sending chat content could inject markup that is subsequently interpreted by multiple excerpt-rendering surfaces, including chat channel lists, chat summary emails, pinned message bars, reply previews, and thread previews. While JavaScript execution was not demonstrated under default Content Security Policy settings, sites that disable or relax CSP face increased exposure, and the CVSS 3.1 base score of 5.0 reflects a low integrity impact.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Technical Analysis
The vulnerability class is CWE-79 (Improper Neutralization of Input During Web Page Generation, commonly "Cross-Site Scripting"). Per the NVD description, the root cause is that an upload's filename is attacker-controlled, and when that filename is incorporated into a chat message excerpt, it is rendered as unescaped HTML rather than being encoded for the output context.
The attack surface centers on the chat subsystem's excerpt renderers. The description explicitly names several surfaces that interpret the injected markup:
- Chat channel lists
- Chat summary emails
- Pinned message bars
- Reply previews
- Thread previews
- "Other excerpt renderers" (the description's own wording)
The key distinguishing characteristic of this finding is its classification as trusted-HTML injection rather than classic reflected/stored XSS with demonstrated script execution. Discourse's rendering pipeline applies sanitization/escaping differently depending on whether content is treated as trusted HTML or as untrusted user input. Here, the filename value appears to have traversed a code path that assumed trusted HTML, so the escaping step was skipped.
The advisory explicitly notes that JavaScript execution was not demonstrated with default Content Security Policy settings. This is a material caveat: default CSP acts as a mitigating control that prevents injected inline script from executing. However, CSP does not prevent HTML structure manipulation, content spoofing, link injection, or injection of markup that alters the rendered excerpt. The NVD description further notes an internal inconsistency: the prose advisory states no confidentiality, integrity, or availability impact was identified, while the structured scoring metadata separately assigns a low integrity impact. This report defers to the CVSS vector (I:L, C:N, A:N) for scoring purposes.
Because no code-level specifics (function names, template paths, sanitizer names) are present in the provided intelligence, the precise escaping failure cannot be pinpointed. What can be stated definitively from the description is the vulnerability class (HTML injection via unescaped filename output in excerpt renderers), the required attacker capability (ability to upload a file and send chat content), and the affected rendering surfaces enumerated above.
Exploitation Scenarios
No public PoC, exploit code, or Nuclei template exists for CVE-2026-91121, and EPSS has not yet been scored. The attack chain below is inferred from the vulnerability class and the explicit details in the NVD description.
1) Reconnaissance / target identification. An adversary identifies a Discourse instance running a version prior to the fixed releases (2026.1.8, 2026.6.3, 2026.7.2, 2026.8.0). Instances can be fingerprinted by Discourse's characteristic page titles and HTML. The attacker also needs to determine whether the chat feature is enabled and whether the deployment retains Discourse's default CSP; sites that disable or relax CSP are explicitly noted in the advisory as having increased exposure.
2) Triggering the flaw class. The attacker must possess an authenticated account with the ability to (a) upload a file and (b) send chat content. The attacker crafts an upload whose filename contains HTML markup. That filename is then carried into chat message excerpt rendering. Because the excerpt renderers fail to escape the filename for the HTML output context, the included markup is interpreted as HTML rather than displayed as literal text.
3) Payload placement at the vulnerability-class level. Rather than injecting through the chat message body — which is presumably escaped — the injection vector is the filename metadata attached to an uploaded file. The payload is therefore an HTML fragment (not demonstrated to be executable JavaScript under default CSP), which propagates into every excerpt surface that references the affected upload: chat channel lists, chat summary emails, pinned message bars, reply previews, and thread previews.
4) Post-exploitation impact. Under default CSP, the demonstrated impact is trusted-HTML injection that alters rendered excerpt content — i.e., content spoofing, markup/structural manipulation of excerpts, and potential injection of links or other non-script HTML within the application's trusted rendering context. On deployments with relaxed or disabled CSP, the advisory notes increased exposure, meaning the injection could potentially escalate toward script execution; however, the advisory does not demonstrate this. No confidentiality or availability impact was identified, and structured scoring assigns only low integrity impact.
Impact Assessment
The CVSS 3.1 base score is 5.0 (Medium) with vector CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:N/I:L/A:N.
Subscore interpretation:
- AV:N (Network) — exploitable remotely over the network; no adjacent or local access required.
- AC:L (Low) — no special conditions or race windows; the injection is straightforward once the attacker can upload and chat.
- PR:L (Low) — requires a low-privileged authenticated account able to upload files and send chat messages.
- UI:N (None) — no victim interaction is required for the injection itself; however, the impact of excerpt rendering inherently depends on other users (or email recipients) viewing the affected excerpts.
- S:C (Changed) — the security scope changes, consistent with markup being rendered in a context whose permissions/trust assumptions differ from the input context (i.e., trusted-HTML rendering of attacker-influenced data).
- C:N / I:L / A:N — no confidentiality impact; low integrity impact (rendered content can be altered); no availability impact.
Blast radius. Any Discourse deployment running an affected version with chat enabled and uploads permitted is in scope. Because affected excerpts include chat summary emails, injection can reach recipients outside the platform itself, broadening exposure beyond logged-in users. The integrity impact is bounded — content alteration rather than data exfiltration or service disruption — but trusted-HTML injection in a platform's own rendering context can still undermine user trust in displayed content. Sites that disable or relax the default CSP should be treated as the highest-priority remediation targets given the advisory's explicit statement on increased exposure.
Detection Guidance
Sigma Rule
title: Discourse Chat Excerpt Filename HTML Injection (CVE-2026-91121)
id: 7f3c1a92-4b6e-4d21-9c88-0a1e5f2b7d34
status: experimental
description: Detects file uploads whose filename contains HTML markup, consistent with trusted-HTML injection into Discourse chat excerpt renderers prior to 2026.1.8, 2026.6.3, 2026.7.2, 2026.8.0.
references:
- https://nvd.nist.gov/vuln/detail/CVE-2026-91121
author: Threat Intelligence
date: 2026/01/01
logsource:
category: web
product: discourse
detection:
keywords:
- '<'
- '>'
filename_patterns:
- '.*<[a-zA-Z/].*>.*'
- '.*&#[0-9]+;.*'
- '.*<.*>.*'
condition: filename_patterns
falsepositives:
- Legitimate filenames containing angle brackets (rare)
level: medium
tags:
- attack.t1190
- cve.2026.91121
YARA Rule
rule CVE_2026_91121_Discourse_Filename_HTML_Injection
{
meta:
description = "Detects HTML markup in uploaded filenames potentially targeting Discourse chat excerpt renderers (CVE-2026-91121)"
reference = "https://nvd.nist.gov/vuln/detail/CVE-2026-91121"
author = "Threat Intelligence"
date = "2026-01-01"
severity = "medium"
strings:
$html_tag = /<[a-zA-Z][a-zA-Z0-9]*[^>]*>/
$script_tag = "<script"
$img_tag = "<img"
$iframe_tag = "<iframe"
$onerror = "onerror="
$onload = "onload="
$entity_lt = "<"
$entity_gt = ">"
condition:
(any of ($html_tag, $script_tag, $img_tag, $iframe_tag)) or
($entity_lt and $entity_gt) or
(any of ($onerror, $onload))
}
Suricata IDS Rule
alert http any any -> any any (msg:"CVE-2026-91121 Discourse Chat Filename HTML Injection Attempt"; flow:established,to_server; http.method; content:"POST"; http.uri; content:"/uploads"; http.header; content:"Content-Disposition"; pcre:"/filename=\"?[^\"]*<(script|img|iframe|svg)/i"; reference:cve,2026-91121; reference:url,nvd.nist.gov/vuln/detail/CVE-2026-91121; classtype:web-application-attack; sid:202691121; rev:1;)
Elastic Detection
sequence by user.name with maxspan=5m
[http where http.request.method == "POST" and url.path contains "/uploads"]
[http where http.request.method in ("POST", "PUT") and
(http.request.body contains "<script" or
http.request.body contains "<img" or
http.request.body contains "<iframe" or
http.request.body contains "onerror=")]
Splunk SPL Query
index=web sourcetype=discourse
| search (uri_path="*/uploads*" OR uri_path="*/chat*")
| eval suspicious=if(match(filename, "<[a-zA-Z/]") OR match(request_body, "<script|<img|<iframe|onerror=|onload="), 1, 0)
| where suspicious=1
| stats count min(_time) as first_seen max(_time) as last_seen by src_ip, user, uri_path, filename
| sort - count
Wazuh OSSEC Rule
<group name="discourse,web,attack,">
<rule id="2026911" level="10">
<decoded_as>web-accesslog</decoded_as>
<url>upload</url>
<match>filename=</match>
<regex type="pcre2">filename=.*<(script|img|iframe|svg)</regex>
<description>CVE-2026-91121: Possible Discourse chat excerpt filename HTML injection attempt detected</description>
<mitre>
<id>T1190</id>
</mitre>
<group>web_application_attack,pci_dss_6.5,</group>
</rule>
</group>
Mitigation & Patch Guidance
Patch confidence: 0/4 — UNPATCHED — no patch evidence from any tracked source. Although the NVD description references fixed versions (2026.1.8, 2026.6.3, 2026.7.2, 2026.8.0), no vendor patch artifact, commit, or advisory has been independently captured or verified, and no CISA KEV listing exists.
1) Immediate mitigations (interim):
- Enforce and do not relax Discourse's default Content Security Policy. The advisory states JavaScript execution was not demonstrated under default CSP, and that sites disabling or relaxing CSP have increased exposure. Treat any CSP relaxation as a direct amplifier of this vulnerability.
- Where operationally feasible, temporarily restrict chat functionality or disable file uploads in chat for users who do not strictly require it, reducing the attacker surface implied by the prerequisite "able to upload a file and send chat content."
- Audit existing chat uploads and excerpts for filenames containing markup.
2) Patch / upgrade steps:
- Upgrade Discourse to one of the fixed releases: 2026.1.8, 2026.6.3, 2026.7.2, or 2026.8.0, selecting the version appropriate to your tracked release channel.
- Because patch confidence is 0/4 and no vendor artifact is on record, verify the fix independently after upgrading by testing whether an HTML-bearing filename is escaped in each affected excerpt renderer (chat channel lists, chat summary emails, pinned message bars, reply previews, thread previews).
- Track the NVD entry and the project's official release notes for confirmation that the fix addresses the escaping gap, since the advisory's own prose and structured scoring metadata are reported as inconsistent regarding integrity impact.
3) Long-term hardening:
- Adopt output-context-aware encoding for all metadata-derived values (including filenames) that flow into HTML templates, so that "trusted HTML" rendering paths never receive attacker-controlled strings unescaped.
- Maintain a strict, non-relaxed CSP as a defense-in-depth layer for the entire class of HTML injection issues.
- Add automated tests that assert filenames and other upload metadata are escaped across every excerpt renderer, preventing regression.
- Deploy detection coverage (see Detection Guidance) to identify upload filenames containing markup as an early-warning signal.
References
- NVD — CVE-2026-91121: https://nvd.nist.gov/vuln/detail/CVE-2026-91121
- CWE-79 (Improper Neutralization of Input During Web Page Generation): https://cwe.mitre.org/data/definitions/79.html
- Discourse project (official releases and security advisories): https://github.com/discourse/discourse/releases
- FIRST EPSS (score not yet assigned at time of writing): https://www.first.org/epss/
- CISA Known Exploited Vulnerabilities Catalog (CVE-2026-91121 not listed): https://www.cisa.gov/known-exploited-vulnerabilities-catalog
No threat actor campaigns, exploit-in-the-wild evidence, public PoC, Nuclei template, or exploit code are associated with CVE-2026-91121 as of this report.
What is this? Security researchers use these exact search queries on Shodan.io (a search engine for internet-connected devices) to find vulnerable systems globally. You can copy these dorks to see if your organization's IP space is exposed.