CVE-2026-91132 Overview
Discourse is an open-source discussion platform used by communities and enterprises for forums and support. CVE-2026-91132 is an origin validation flaw [CWE-346] affecting sites that configure wildcard patterns in the allowed_iframes setting. The wildcard origin check matches the allowed domain text, while browser URL parsing resolves a different attacker-controlled origin. A user with posting privileges can embed an attacker-controlled iframe through a post or a Onebox oEmbed response. The issue is fixed in versions 2026.1.8, 2026.6.3, 2026.7.2, and 2026.8.0.
Critical Impact
Authenticated users on sites using wildcard allowed_iframes patterns can render arbitrary attacker-controlled iframes, enabling content spoofing, phishing surfaces, and click-driven attacks against other forum users.
Affected Products
- Discourse versions prior to 2026.1.8
- Discourse versions prior to 2026.6.3 and 2026.7.2
- Discourse versions prior to 2026.8.0
Discovery Timeline
- 2026-09-24 - CVE-2026-91132 published to NVD
- 2026-09-29 - Last updated in NVD database
Technical Details for CVE-2026-91132
Vulnerability Analysis
The flaw lives in how Discourse translates allowed_iframes wildcard patterns into regular expressions used to validate iframe source URLs. The sanitizer in frontend/pretty-text/addon/sanitizer.js and the Onebox engine in lib/onebox/engine.rb both replace the wildcard character with a character class that is too permissive. Specifically, the pattern allows characters that act as URL authority delimiters, so a crafted URL can place the allowlisted suffix before an attacker-controlled authority. The server-side regex evaluates the URL as matching the allowlist, but the browser parses the real origin from the authority segment following @, \, or similar separators. The result is a divergence between the security decision and the rendered origin, letting an attacker-controlled iframe load alongside trusted embeds.
Root Cause
The sanitizer compiled wildcard patterns using .replace(/\*/g, "[^/]+"), and the Ruby Onebox engine used [^/?#]*. Neither accounted for backslash (\), which some browsers treat as equivalent to / when parsing a URL authority. The regex therefore extended past the host boundary, allowing a different effective origin to be chosen by the browser than the one validated by Discourse.
Attack Vector
Exploitation requires an authenticated account with posting privileges and a Discourse site that has configured at least one wildcard pattern in allowed_iframes. The attacker submits content that produces an iframe, either directly in a post or via a Onebox oEmbed response from an attacker-controlled URL. The server validates the URL against the overly permissive regex and renders the iframe. Browsers resolve the authority to the attacker's origin, so the embedded frame delivers content outside the intended allowlist.
// Patch in frontend/pretty-text/addon/sanitizer.js
const regex = i
// escape regex, keeping *
.replace(/[.+?^${}()|[\]\\]/g, "\\$&")
- .replace(/\*/g, "[^/]+");
+ .replace(/\*/g, "[^/?#\\\\]+");
const allowedIframe = new RegExp(`^${regex}.*$`, "i");
return iframeUrls.every((iframeUrl) =>
allowedIframe.test(iframeUrl)
Source: Discourse Commit 8096870
# Patch in lib/onebox/engine.rb
origins.map do |origin|
escaped_origin = Regexp.escape(origin)
if origin.start_with?("*.", "https://*.", "http://*.")
- escaped_origin = escaped_origin.sub("\\*", "[^/?#]*")
+ escaped_origin = escaped_origin.sub("\\*") { "[^/?#\\\\]*" }
end
origin_boundary =
Source: Discourse Commit 8096870
The fix narrows the wildcard expansion to exclude /, ?, #, and \, keeping expansion bounded to the authority segment of the URL.
Detection Methods for CVE-2026-91132
Indicators of Compromise
- Rendered iframe src attributes containing authority delimiters such as @, \, or encoded variants placed between the allowlisted suffix and an unexpected host.
- Onebox oEmbed responses from external URLs that trigger iframe insertion for origins not previously seen in the site's content.
- Posts from newly registered or low-reputation accounts that embed media from allowed_iframes wildcard domains with unusual URL formats.
Detection Strategies
- Audit the allowed_iframes site setting for wildcard entries, then scan historical post content for iframe tags whose host portion contains \, @, or percent-encoded authority characters.
- Inspect HTTP logs for Onebox requests to external URLs whose returned iframe HTML embeds a host outside the configured allowlist.
- Monitor Content Security Policy (CSP) violation reports for frame-src entries matching unexpected origins.
Monitoring Recommendations
- Enable and centralize Discourse application logs, correlating post creation events with subsequent iframe rendering decisions.
- Alert on changes to the allowed_iframes setting and review wildcard patterns during each change.
- Track outbound Onebox fetches for unusual response payloads containing iframe markup.
How to Mitigate CVE-2026-91132
Immediate Actions Required
- Upgrade Discourse to 2026.1.8, 2026.6.3, 2026.7.2, or 2026.8.0 depending on your release branch.
- Review and tighten allowed_iframes to use fully qualified hostnames rather than wildcard patterns where possible.
- Audit recent posts and Onebox embeds for suspicious iframe sources since the vulnerable configuration was introduced.
Patch Information
The vendor fix is tracked in Discourse Security Advisory GHSA-4q3q-hph3-3rvp and implemented in Discourse Pull Request #42882. The patch updates the wildcard-to-regex translation in both frontend/pretty-text/addon/sanitizer.js and lib/onebox/engine.rb to exclude URL authority delimiters, including backslash.
Workarounds
- Remove wildcard entries from allowed_iframes until the upgrade is applied; the vulnerability only affects wildcard patterns.
- Restrict posting privileges to trusted users and disable Onebox fetching for untrusted URLs on exposed instances.
- Deploy a strict Content Security Policy with an explicit frame-src allowlist to reduce the impact of rendered iframes.
# Example: temporarily remove wildcard allowed_iframes via rails console
cd /var/discourse
./launcher enter app
rails runner 'SiteSetting.allowed_iframes = "https://www.google.com/maps/embed?|https://trusted.example.com/"'
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.