Skip to main content
Vulnerability Database/CVE-2026-91122

CVE-2026-91122: Discourse Video Placeholder XSS Vulnerability

CVE-2026-91122 is a stored XSS vulnerability in Discourse video placeholder component allowing authenticated attackers to inject malicious event handlers. This post explains its impact, affected versions, and mitigation steps.

Published:

CVE-2026-91122 Overview

Discourse, an open-source discussion platform, contains a stored Cross-Site Scripting (XSS) vulnerability in its video placeholder component. The flaw allows crafted HTML to break out of an attribute context and inject an attacker-controlled event handler. An authenticated user with default trust-level posting privileges can store the malicious placeholder in a post. When another user views the post and clicks the video play overlay, the handler can execute arbitrary JavaScript in the viewer's session.

The vulnerability is tracked under CWE-79: Improper Neutralization of Input During Web Page Generation and is fixed in Discourse versions 2026.1.8, 2026.6.3, 2026.7.2, and 2026.8.0.

Critical Impact

Exploitation lets a low-privileged forum user execute JavaScript in a viewer's authenticated session, read page content, and issue requests as that user when Content Security Policy (CSP) is disabled or relaxed.

Affected Products

  • Discourse versions prior to 2026.1.8
  • Discourse versions prior to 2026.6.3
  • Discourse versions prior to 2026.7.2 and prior to 2026.8.0

Discovery Timeline

  • 2026-09-24 - CVE-2026-91122 published to the National Vulnerability Database (NVD)
  • 2026-09-24 - Last updated in NVD database

Technical Details for CVE-2026-91122

Vulnerability Analysis

The vulnerability resides in the Discourse frontend video placeholder initializer at frontend/discourse/app/instance-initializers/video-placeholder.js. The sanitizeUrl routine filters HTML-encoded angle brackets (> and <) but fails to reject double-quote characters. When the sanitized value is interpolated into an HTML attribute, an embedded " closes the attribute early and allows an attacker to inject additional attributes, including JavaScript event handlers such as onclick.

Because the payload is persisted inside a post, exploitation becomes stored XSS. Any user who opens the post and interacts with the video play overlay triggers the injected handler in their own browser context.

Root Cause

The root cause is incomplete input sanitization in the video placeholder URL handler. The sanitizer treats encoded angle brackets as the sole indicator of unsafe markup and does not account for attribute-delimiter characters. This mismatch between the sanitizer's assumptions and the HTML attribute context the value is injected into produces the attribute breakout.

Attack Vector

An authenticated attacker with default posting privileges crafts a video placeholder containing a double-quote and malicious attribute payload. The post is stored normally in the Discourse database. When another authenticated user loads the post and clicks the play overlay, the injected handler executes under the viewer's origin. Default Discourse Content Security Policy settings block inline event handlers, but instances that have disabled or relaxed CSP are directly exploitable, enabling the script to read page DOM content and issue authenticated requests as the viewer.

javascript
// Patch excerpt - sanitizer now also rejects the double-quote character
              sanitized &&
              sanitized.trim() !== "" &&
              !sanitized.includes(">") &&
-             !sanitized.includes("<")
+             !sanitized.includes("<") &&
+             !sanitized.includes('"')
            ) {
              return sanitized;
            }
// Source: https://github.com/discourse/discourse/commit/05d92b8749f68d2626cbe65ec7adde7562a0283d

Detection Methods for CVE-2026-91122

Indicators of Compromise

  • Posts containing video placeholder markup with embedded double-quote characters or unexpected on* event handler attributes.
  • Browser console errors referencing CSP violations tied to inline script or event handlers originating from forum post rendering.
  • Outbound requests from authenticated user sessions to attacker-controlled domains shortly after loading forum content.

Detection Strategies

  • Review the Discourse posts table for stored content containing " adjacent to video embed markup or onclick, onerror, or onload strings inside video placeholder elements.
  • Enable and audit CSP report-only or enforcement reports to surface attempts to execute inline event handlers in rendered posts.
  • Correlate web proxy or Endpoint Detection and Response (EDR) telemetry for anomalous requests to the Discourse API originating from user browsers after viewing specific posts.

Monitoring Recommendations

  • Monitor Discourse application logs for unusual activity from accounts newly reaching default trust-level posting privileges.
  • Alert on CSP violation reports generated by rendered forum pages, treating repeat violations as potential exploitation attempts.
  • Track administrative account sessions for unexpected authenticated API calls that follow forum browsing activity.

How to Mitigate CVE-2026-91122

Immediate Actions Required

  • Upgrade Discourse to a fixed release: 2026.1.8, 2026.6.3, 2026.7.2, or 2026.8.0 depending on the deployed branch.
  • Audit existing posts for crafted video placeholder markup and remove or neutralize any suspicious content before upgrading.
  • Confirm that Content Security Policy is enabled with default restrictive settings until the patch is applied.

Patch Information

The fix adds a rejection for the " character in the sanitizeUrl logic of video-placeholder.js. The relevant commits are 05d92b8, 5674b3e, c3993e3, and d7126af, delivered through Pull Request #42882. Full technical context is published in GitHub Security Advisory GHSA-8m44-f6g9-7cg7.

Workarounds

  • Re-enable the default Discourse Content Security Policy, which blocks inline event handlers and prevents the injected handler from executing.
  • Raise the trust level required for posting video embeds, limiting the pool of accounts that can store placeholder payloads.
  • Temporarily disable video placeholder rendering through site customization until the patched version is deployed.
bash
# Enable the default Content Security Policy via Discourse admin site settings
# Navigate to: Admin -> Settings -> Security
# Ensure the following are enabled:
#   content_security_policy = true
#   content_security_policy_strict_dynamic = true
# Then rebuild the application container
cd /var/discourse
./launcher rebuild app

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.