CVE-2026-91134
Executive Summary
CVE-2026-91134 is a stored cross-origin iframe sanitizer bypass in Discourse, the open-source discussion platform. An authenticated user with posting privileges can persist an iframe whose src contains encoded userinfo, causing the post sanitizer's allowed_iframes prefix policy to validate a decoded URL while the browser interprets an attacker-controlled host. Successful exploitation renders attacker-controlled cross-origin content inside forum posts, affecting confidentiality and integrity at Low severity (CVSS 5.4). The issue is fixed in 2026.1.8, 2026.6.3, 2026.7.2, and 2026.8.0; no public PoC or in-the-wild exploitation is currently known.
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
Discourse uses the allowed_iframes setting to restrict which external frames may be embedded in posts. Prior to the listed fix versions, the post sanitizer performed prefix validation against a decoded form of the iframe src, but stored (and thus browser-interpreted) the raw encoded form. When the src contains encoded userinfo, the two representations resolve to different origins: the sanitizer sees an allowed-prefix string, while the browser parses an alternate host supplied via the encoded userinfo component. The allowlist check and the actual origin rendered by the browser therefore diverge.
The flaw class is CWE-20 (Improper Input Validation), specifically a canonicalization/decoding mismatch. This is a classic security-relevant failure: validation on one representation and enforcement on another. The attack surface is any Discourse deployment with user-generated post content and cross-origin iframe embedding governed by allowed_iframes. The NVD description does not specify the exact sanitization routine, parsing library, or the precise string comparison logic, so those implementation details are not asserted here. No encoding, header, or browser-quirk specifics beyond "encoded userinfo in iframe src" are established by the source data.
Because the sanitizer and the browser disagree on the effective origin, the impact is limited to rendering attacker-chosen cross-origin content within a trusted post context; it is not a server-side code execution flaw. CVSS subscores C:L and I:L reflect the constrained cross-origin content injection, while A:N and the unchanged Scope (S:U) reflect no direct availability impact and no privilege boundary crossing beyond the rendered frame.
Exploitation Scenarios
No public PoC is available; the chain below is inferred from the vulnerability class (stored sanitizer canonicalization bypass) and the NVD description, without fabricating implementation specifics.
Reconnaissance/target identification: An attacker identifies a Discourse instance running a version prior to the fix releases, and determines whether cross-origin iframe embedding is permitted via the
allowed_iframespolicy. Authentication is required — the attacker needs an account with posting privileges (PR:L).Triggering the flaw class: The attacker composes a post containing an iframe whose
srcincludes encoded userinfo, crafted so that the sanitizer's decoded prefix check matches an allowed entry while the browser resolves an attacker-controlled host.Payload/execution method: The payload is persisted as post content. On render, the sanitizer dependency accepts the decoded URL as an allowed prefix, but the browser interprets the encoded userinfo and loads the attacker-controlled cross-origin frame. The frame content is delivered from the attacker's host.
Post-exploitation impact: Rendered cross-origin content appears within the trusted forum context. This can support content spoofing, phishing scaffolding, or embedding of attacker-controlled external interfaces, with Low confidentiality and integrity impact. No public exploit code, Nuclei template, or in-the-wild campaign is documented.
Impact Assessment
Business impact centers on trust and content integrity within hosted community platforms. Because the injected frame is cross-origin and controlled by the attacker, users may be exposed to misleading or malicious embedded content presented as part of the forum. CVSS 5.4 (AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:N) indicates a moderately scored, network-reachable issue requiring low privileges, no user interaction, and no scope change. Blast radius is bounded to readability of rendered posts and potential secondary phishing, not to server compromise. Affected systems are Discourse deployments below the fixed versions, particularly those with cross-origin iframe embedding enabled and open registration or broad posting rights.
Detection Guidance
Sigma Rule
title: Discourse Post Stored Cross-Origin Iframe Sanitizer Bypass Attempt
id: 8f1c2d34-9b7e-4a1f-9d21-7c0e5f9a1b23
status: experimental
description: Detects post content containing iframe src values with encoded userinfo, consistent with CVE-2026-91134 sanitizer bypass.
logsource:
product: discourse
service: web
detection:
selection_body:
body|contains:
- '<iframe'
selection_userinfo:
body|re:
- '(?i)<iframe[^>]+src\s*=\s*["'']?[a-z]+://[^/?#@]+%40'
- '(?i)<iframe[^>]+src\s*=\s*["'']?[a-z]+://[^/?#@]+%3A[^/?#@]*%40'
condition: selection_body and selection_userinfo
falsepositives:
- Legitimate iframe embeds from allowlisted domains containing encoded characters
level: medium
tags:
- attack.t1190
- cve.2026-91134
YARA Rule
rule CVE_2026_91134_Discourse_Iframe_Userinfo_Bypass
{
meta:
description = "Detects iframe src with encoded userinfo targeting Discourse allowed_iframes bypass (CVE-2026-91134)"
author = "valtersit.com"
date = "2026-01-01"
reference = "CVE-2026-91134"
severity = "medium"
strings:
$iframe = "<iframe" nocase
$src1 = "src=" nocase
$u1 = "%40" nocase
$u2 = "%2540" nocase
$u3 = "%3a" nocase
condition:
$iframe and $src1 and any of ($u*)
}
Suricata IDS Rule
alert http any any -> any any (msg:"CVE-2026-91134 Discourse Stored Iframe Userinfo Sanitizer Bypass"; flow:established,to_server; http.method; content:"POST"; http.request_body; content:"<iframe"; nocase; http.request_body; content:"src"; nocase; http.request_body; content:"%40"; nocase; reference:cve,2026-91134; classtype:web-application-attack; sid:202691134; rev:1;)
Elastic Detection
sequence by user.name with maxspan=5m
[http where http.request.method == "POST" and http.request.body contains "<iframe"]
[http where http.request.body contains "<iframe" and (http.request.body contains "%40" or http.request.body contains "%3A" or http.request.body contains "%2540")]
Splunk SPL Query
index=web sourcetype=access_combined_or_json
| search (uri_path="*/posts*" OR uri_path="*/posts.json*" OR uri_path="*/post*")
| search request_body="*<iframe*" AND (request_body="*%40*" OR request_body="*%3A*" OR request_body="*%2540*")
| stats count min(_time) as first_seen max(_time) as last_seen by src_ip, uri_path, user
| where count > 0
| convert ctime(first_seen) ctime(last_seen)
Wazuh OSSEC Rule
<group name="discourse,cve-2026-91134,">
<rule id="202691134" level="8">
<decoded_as>json</decoded_as>
<field name="request_body">\.*<iframe\.*</field>
<field name="request_body">\.*(%40|%3A|%2540)\.*</field>
<description>CVE-2026-91134: Discourse post may contain cross-origin iframe with encoded userinfo sanitizer bypass.</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).
Immediate mitigations: Upgrade to a fixed release (2026.1.8, 2026.6.3, 2026.7.2, or 2026.8.0). Until then, tighten the
allowed_iframespolicy (restrict or disable cross-origin embedding), reduce posting privileges for untrusted users, and add content filters that flag<iframebodies containing encoded userinfo (%40,%3A, or double-encoded variants). Apply WAF/pre-render filtering to inspect raw encodedsrcvalues rather than decoded representations.Patch/upgrade steps: Deploy the fixed version for your release track, restart Discourse, and re-validate that
allowed_iframesbehaves as intended post-upgrade. No vendor patch artifacts were tracked at the time of analysis, so verify the fix directly against the release notes for the version in use.Long-term hardening: Perform canonicalization consistently — validate the exact representation that will be interpreted downstream — and add regression tests for encoded userinfo/authority parsing in sanitizer pipelines. Adhere to an allowlist (never denylist) for embeddable origins, monitor for sanitizer/parser divergence in trusted-content rendering paths, and keep Discourse on supported tracks.
References
- NVD: https://nvd.nist.gov/vuln/detail/CVE-2026-91134
- Discourse official project: https://github.com/discourse/discourse
- Discourse release/security notes: https://github.com/discourse/discourse/releases
- CWE-20 Improper Input Validation: https://cwe.mitre.org/data/definitions/20.html
- CISA KEV: Not applicable (CVE-2026-91134 not listed)
- Threat actor campaigns / exploit-in-the-wild: None observed; no public PoC or Nuclei template available.
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.