/

CVE-2026-91159

Severity:

HIGH RISK

(7.7)

Content Injection (CWE-79) in Discourse oEmbed Processing

CVE-2026-91159

Deferred

Vulnerability type

Category:

Content Injection and Stored UI Redressing

CWE:

CWE-79

Impact:

Content Integrity Compromise and Misleading User Interfaces

Severity:

HIGH RISK

(7.7)

CVSS version:

3.1

Catch this CVE while code is being written

Detect vulnerable code directly in pull requests, so CVEs are fixed before merge.

Summary

A flaw in Discourse oEmbed processing can cause attacker-controlled sibling HTML or CSS to be treated as trusted when an embedded iframe matches the configured allowlist. A user with posting permission who controls a public webpage and its oEmbed response may inject stored visual overlays or styled content that makes fraudulent or misleading interfaces appear in posts.

A flaw in Discourse oEmbed processing can cause attacker-controlled sibling HTML or CSS to be treated as trusted when an embedded iframe matches the configured allowlist. A user with posting permission who controls a public webpage and its oEmbed response may inject stored visual overlays or styled content that makes fraudulent or misleading interfaces appear in posts.

Affected context

The issue occurs in Discourse installations that process oEmbed responses containing an allowlisted iframe and preserve related attacker-controlled HTML or CSS as trusted post content. It requires a posting workflow that fetches the external oEmbed response and a configured iframe source that is permitted by the site's allowlist. The described behavior affects rendered content integrity rather than restricted data confidentiality or service availability.

The issue occurs in Discourse installations that process oEmbed responses containing an allowlisted iframe and preserve related attacker-controlled HTML or CSS as trusted post content. It requires a posting workflow that fetches the external oEmbed response and a configured iframe source that is permitted by the site's allowlist. The described behavior affects rendered content integrity rather than restricted data confidentiality or service availability.

Exploit preconditions

  • Attack surface: Discourse post creation and oEmbed response processing
  • Required access: A user account with permission to create posts
  • External control: The attacker must control a public webpage and the oEmbed response returned for it
  • Configuration requirement: The response must contain an iframe source that matches a configured allowlist
  • Trigger point: Processing and storage of the oEmbed-derived content
  • Why exploitation is possible: The parser trusts the broader HTML fragment when the iframe itself is allowlisted, allowing unrelated sibling markup or styling to be retained
  • Attack surface: Discourse post creation and oEmbed response processing
  • Required access: A user account with permission to create posts
  • External control: The attacker must control a public webpage and the oEmbed response returned for it
  • Configuration requirement: The response must contain an iframe source that matches a configured allowlist
  • Trigger point: Processing and storage of the oEmbed-derived content
  • Why exploitation is possible: The parser trusts the broader HTML fragment when the iframe itself is allowlisted, allowing unrelated sibling markup or styling to be retained

Why this happens

The underlying bug is an overly broad trust decision in oEmbed sanitization. Validation of an allowlisted iframe source was effectively treated as sufficient justification for trusting the surrounding HTML fragment, including unrelated elements or CSS. This maps to CWE-79 because insufficient neutralization of attacker-controlled HTML can allow active or deceptive content to be stored and rendered in a user's post context.

The underlying bug is an overly broad trust decision in oEmbed sanitization. Validation of an allowlisted iframe source was effectively treated as sufficient justification for trusting the surrounding HTML fragment, including unrelated elements or CSS. This maps to CWE-79 because insufficient neutralization of attacker-controlled HTML can allow active or deceptive content to be stored and rendered in a user's post context.

Potential impact

  • Stored posts may display misleading overlays or fraudulent interface elements
  • Users may be deceived about links, controls, authorship, or other post content
  • The integrity and visual presentation of discussion content may be altered
  • The issue could support phishing or social-engineering campaigns within the platform
  • It may undermine trust in rendered post content without exposing restricted data or disrupting availability
  • Stored posts may display misleading overlays or fraudulent interface elements
  • Users may be deceived about links, controls, authorship, or other post content
  • The integrity and visual presentation of discussion content may be altered
  • The issue could support phishing or social-engineering campaigns within the platform
  • It may undermine trust in rendered post content without exposing restricted data or disrupting availability

General mitigation guidance

Mitigation generally focuses on applying trust decisions to the complete

rendered fragment rather than inferring safety from one approved element.

Common defensive patterns include:

  • Sanitize all HTML and CSS from external oEmbed responses using an allowlist-based policy
  • Permit only explicitly supported element, attribute, URL, and style combinations
  • Treat iframe approval independently from surrounding markup and discard unrelated content
  • Normalize and validate content before storage and again at rendering boundaries where appropriate
  • Keep external content in isolated containers with restrictive framing and scripting policies
  • Limit posting and embedding privileges according to user and tenant trust levels
  • Apply contextual output encoding and preserve a restrictive content security policy

Mitigation generally focuses on applying trust decisions to the complete

rendered fragment rather than inferring safety from one approved element.

Common defensive patterns include:

  • Sanitize all HTML and CSS from external oEmbed responses using an allowlist-based policy
  • Permit only explicitly supported element, attribute, URL, and style combinations
  • Treat iframe approval independently from surrounding markup and discard unrelated content
  • Normalize and validate content before storage and again at rendering boundaries where appropriate
  • Keep external content in isolated containers with restrictive framing and scripting policies
  • Limit posting and embedding privileges according to user and tenant trust levels
  • Apply contextual output encoding and preserve a restrictive content security policy

How teams detect issues like this

Organizations can look for this class of issue through:

  • Static analysis and code review checks for trust decisions based only on nested or partial HTML validation
  • Tests that submit allowlisted iframes alongside disallowed sibling elements, styles, and attributes
  • Review of oEmbed sanitizers for complete-fragment parsing, URL validation, CSS handling, and storage behavior
  • Policy checks requiring external content to pass a centralized HTML sanitization boundary
  • Runtime monitoring for unexpected iframe, style, overlay, or positioning content in user-generated posts
  • Automated security testing that compares sanitized output against an approved element and attribute policy

Organizations can look for this class of issue through:

  • Static analysis and code review checks for trust decisions based only on nested or partial HTML validation
  • Tests that submit allowlisted iframes alongside disallowed sibling elements, styles, and attributes
  • Review of oEmbed sanitizers for complete-fragment parsing, URL validation, CSS handling, and storage behavior
  • Policy checks requiring external content to pass a centralized HTML sanitization boundary
  • Runtime monitoring for unexpected iframe, style, overlay, or positioning content in user-generated posts
  • Automated security testing that compares sanitized output against an approved element and attribute policy

Sources

SourceLink
github.comgithub.com/discourse/discourse/commit/0953b31f5c2949d7d6ab5f6dc4c5e2f1b8bf0b22
github.comgithub.com/discourse/discourse/commit/3fc2bad6cdca47b00958330d1ee612aa141b039a
github.comgithub.com/discourse/discourse/commit/dde8bc4fb6200139f5eff7e100b0f3e829d37ab3
github.comgithub.com/discourse/discourse/commit/ed6f83f123d1a4c6c6c7e64c8a2233e3cb6a28d7
github.comgithub.com/discourse/discourse/security/advisories/GHSA-f9jx-vv33-4282

Frequently asked

questions

It can be triggered through normal Discourse posting and oEmbed processing when

the attacker controls the required external webpage and has a matching

allowlisted iframe source. It does not require direct server access.

The attacker needs permission to create posts, control the fetched webpage and

its oEmbed response, and satisfy the site's iframe allowlist configuration.

The described issue primarily affects content integrity and visual presentation.

It does not inherently expose restricted data, disrupt availability, or require

interaction with Discourse Content Security Policy.

Treat the entire external HTML fragment as untrusted, sanitize it with a strict

allowlist, and independently validate iframe sources, attributes, and styles

before storing or rendering the result.

Use centralized output sanitization, test nested and sibling markup combinations,

restrict embedding privileges, and enforce review policies that prevent partial

validation from establishing trust for an entire document fragment.

It can be triggered through normal Discourse posting and oEmbed processing when

the attacker controls the required external webpage and has a matching

allowlisted iframe source. It does not require direct server access.

The attacker needs permission to create posts, control the fetched webpage and

its oEmbed response, and satisfy the site's iframe allowlist configuration.

The described issue primarily affects content integrity and visual presentation.

It does not inherently expose restricted data, disrupt availability, or require

interaction with Discourse Content Security Policy.

Treat the entire external HTML fragment as untrusted, sanitize it with a strict

allowlist, and independently validate iframe sources, attributes, and styles

before storing or rendering the result.

Use centralized output sanitization, test nested and sibling markup combinations,

restrict embedding privileges, and enforce review policies that prevent partial

validation from establishing trust for an entire document fragment.

Find out what's already
exploitable in your codebase.