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

CVE-2026-90561: Strapi CMS Stored XSS Vulnerability

CVE-2026-90561 is a stored XSS flaw in Strapi CMS allowing Author-role users to inject malicious scripts that execute in Editor or Super Admin sessions. This post explains its impact, affected versions, and mitigation steps.

Published:

CVE-2026-90561 Overview

CVE-2026-90561 is a stored cross-site scripting vulnerability [CWE-79] in the Strapi content manager WYSIWYG preview component. The flaw affects Strapi versions 4.x through 4.26.2 and 5.x before 5.48.1. The PreviewWysiwyg component fails to strip script tags from rendered rich text markdown. An authenticated user with the Author role can inject malicious script tags into rich text fields. When an Editor or Super Admin expands the preview pane, the injected script executes in their authenticated session. This enables account takeover of higher-privileged administrative accounts within the Strapi admin panel.

Critical Impact

Low-privilege Author accounts can escalate to Super Admin by executing arbitrary JavaScript in an administrator's browser session, leading to full compromise of the Strapi content management system.

Affected Products

  • Strapi 4.x through 4.26.2
  • Strapi 5.x before 5.48.1
  • Strapi content manager WYSIWYG preview component (PreviewWysiwyg.tsx)

Discovery Timeline

  • 2026-09-13 - CVE-2026-90561 published to the National Vulnerability Database
  • 2026-09-18 - Last updated in NVD database

Technical Details for CVE-2026-90561

Vulnerability Analysis

The vulnerability resides in the PreviewWysiwyg React component located at packages/core/content-manager/admin/src/pages/EditView/components/FormInputs/Wysiwyg/PreviewWysiwyg.tsx. The component renders markdown content through md.render() and then applies sanitize-html with an overly permissive configuration.

The sanitizer was invoked with allowedTags: false, which disables tag filtering entirely. Only a small attribute allowlist was enforced. This allowed dangerous HTML elements including <script>, <iframe>, and event handler attributes to survive sanitization. When the rendered HTML was injected into the DOM via dangerouslySetInnerHTML, the payload executed in the victim's browser context.

Strapi's role-based access control permits Author users to create and edit content in rich text fields. Because Editor and Super Admin users routinely preview Author submissions, the payload reaches privileged sessions through normal editorial workflow.

Root Cause

The root cause is misconfiguration of the sanitize-html library. Setting allowedTags: false disabled the tag allowlist, defeating the primary XSS defense. The attribute allowlist alone cannot block script execution when arbitrary tags are permitted.

Attack Vector

An Author user submits a rich text field containing script tags or event handlers. The payload is stored in the Strapi database. When an Editor or Super Admin opens the entry and expands the WYSIWYG preview pane, the sanitizer passes the script through unchanged and the browser executes it. The attacker script can then exfiltrate the JSON Web Token, create new admin accounts, or modify content using the victim's privileges.

diff
 import * as React from 'react';
 
-import sanitizeHtml from 'sanitize-html';
 import { styled } from 'styled-components';
 
 import { md } from './utils/mdRenderer';
+import { sanitize } from './utils/sanitizer';
 
 interface PreviewWysiwygProps {
   data?: string;
 }
 
 const PreviewWysiwyg = ({ data }: PreviewWysiwygProps) => {
   const html = React.useMemo(
-    () =>
-      sanitizeHtml(md.render((data ?? '').replaceAll('\\n', '\n')), {
-        ...sanitizeHtml.defaults,
-        allowedTags: false,
-        allowedAttributes: {
-          '*': ['href', 'align', 'alt', 'center', 'width', 'height', 'type', 'controls', 'target'],
-          img: ['src', 'alt'],
-          source: ['src', 'type'],
-        },
-      }),
+    () => sanitize(md.render((data ?? '').replaceAll('\\n', '\n'))),
     [data]
   );

Source: Strapi Commit 8757526

Detection Methods for CVE-2026-90561

Indicators of Compromise

  • Rich text field entries containing <script> tags, <iframe> elements, or inline event handlers such as onerror, onload, or onclick
  • Unexpected outbound HTTP requests from administrator browsers to external domains after opening content previews
  • Creation of new Super Admin accounts or role modifications shortly after an Author submits or edits content
  • Anomalous API calls to /admin/users or /content-manager endpoints originating from privileged sessions

Detection Strategies

  • Query the Strapi database directly for rich text content matching XSS payload patterns using regular expressions against markdown fields
  • Enable Content Security Policy reporting to capture script violations in the admin panel
  • Correlate Strapi audit logs of Author-role edits with subsequent privileged administrative actions from Editor or Super Admin accounts

Monitoring Recommendations

  • Monitor Strapi admin panel access logs for privilege escalation patterns following content preview events
  • Alert on any changes to the admin::users collection, particularly role assignments and new account creation
  • Track browser telemetry from administrator workstations for unexpected fetch calls to non-Strapi domains during content review sessions

How to Mitigate CVE-2026-90561

Immediate Actions Required

  • Upgrade Strapi 5.x installations to version 5.48.1 or later immediately
  • Audit all existing rich text content for stored script payloads before administrators open preview panes
  • Review Strapi audit logs for suspicious admin account creation or role changes since Author accounts were provisioned
  • Rotate administrator JWT secrets and force re-authentication of all admin users

Patch Information

The fix is delivered in Strapi 5.48.1 via commit 8757526. The patch replaces sanitize-html with DOMPurify, which enforces a secure-by-default tag allowlist that strips <script>, <iframe>, and other executable elements. See Strapi Issue #26857 and the VulnCheck Advisory for Strapi for additional details. Strapi 4.x users should migrate to a supported 5.x release.

Workarounds

  • Restrict Author role assignments to trusted users only until patches are applied
  • Disable the WYSIWYG preview functionality in the admin panel where feasible
  • Deploy a strict Content Security Policy that blocks inline script execution in the /admin route
  • Place the Strapi admin panel behind a web application firewall configured to filter script tag patterns in POST bodies to content manager endpoints
bash
# Upgrade Strapi to the patched release
npm install @strapi/strapi@5.48.1
# Verify installed version
npm ls @strapi/strapi

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

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

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.