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.
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
# 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.
