CVE-2026-28223 Overview
CVE-2026-28223 is a stored cross-site scripting (XSS) vulnerability affecting Wagtail, an open source content management system built on Django. The vulnerability exists within the wagtail.contrib.simple_translation module's confirmation message handling. A malicious user with access to the Wagtail admin area can craft a page title containing JavaScript code that executes when another administrator performs the "Translate" action on that page.
Critical Impact
Authenticated attackers can execute arbitrary JavaScript in the context of other admin users' sessions, potentially leading to account compromise, privilege escalation, or unauthorized actions within the CMS.
Affected Products
- Wagtail versions prior to 6.3.8
- Wagtail versions 7.0.x prior to 7.0.6
- Wagtail versions 7.2.x prior to 7.2.3
- Wagtail versions 7.3.x prior to 7.3.1
Discovery Timeline
- 2026-03-05 - CVE-2026-28223 published to NVD
- 2026-03-05 - Last updated in NVD database
Technical Details for CVE-2026-28223
Vulnerability Analysis
This stored XSS vulnerability stems from improper output encoding in the Wagtail admin interface's message display system. The wagtail.contrib.simple_translation module generates confirmation messages that include user-controlled page titles. These messages were rendered using Django's |safe template filter, which explicitly bypasses HTML escaping.
When a page is created with a malicious title containing JavaScript (e.g., <script>alert(document.cookie)</script>), this payload is stored in the database. Subsequently, when any administrator performs the "Translate" action on that page, the confirmation message containing the malicious title is rendered without sanitization, causing the JavaScript to execute in the victim's browser context.
The attack requires the attacker to have valid admin credentials with page creation privileges, limiting the attack surface to authenticated users. However, once a malicious page is created, any admin user who interacts with it via the translation feature becomes a potential victim.
Root Cause
The root cause is the use of the |safe template filter in wagtail/admin/templates/wagtailadmin/base.html when rendering flash messages. This filter marks the content as "safe" and prevents Django's automatic HTML escaping, allowing raw HTML including script tags to be injected into the page output.
The vulnerable template code rendered messages as:
{{ message|safe }}
This pattern assumes all message content is pre-sanitized, which is not the case when user-controlled data such as page titles are interpolated into messages.
Attack Vector
The attack vector requires network access and follows a multi-step exploitation chain:
- An attacker with Wagtail admin access creates a new page with a crafted title containing malicious JavaScript
- The malicious page is saved to the database with the XSS payload intact in the title field
- A victim administrator navigates to the malicious page and initiates the "Translate" action
- The simple_translation module generates a confirmation message incorporating the page title
- The message is rendered with |safe, executing the attacker's JavaScript in the victim's browser
- The attacker's script can steal session cookies, perform CSRF attacks, or take actions as the victim user
{% else %}
{% icon name=level_tag classname="messages-icon" %}
{% endif %}
- {{ message|safe }}
+ {{ message }}
{% if level_tag == "error" %}
{# Show a button to focus the first field/response error if available. #}
<button
Source: GitHub Commit 1c6f2eff
The patch removes the |safe filter, allowing Django's default auto-escaping to sanitize all message content, including interpolated user data.
Detection Methods for CVE-2026-28223
Indicators of Compromise
- Presence of page titles containing HTML tags such as <script>, <img onerror=, <svg onload=, or similar XSS payloads in the Wagtail database
- Unexpected JavaScript execution or browser behavior when performing translation actions in the admin interface
- Audit log entries showing pages created with suspicious titles containing encoded or unencoded script tags
Detection Strategies
- Review Wagtail page titles in the database for HTML/JavaScript content using SQL queries or Django ORM filters
- Implement Content Security Policy (CSP) headers to detect and block inline script execution, with violation reports sent to a monitoring endpoint
- Deploy web application firewall (WAF) rules to detect XSS patterns in form submissions to the Wagtail admin
Monitoring Recommendations
- Enable detailed logging for page creation and modification events in the Wagtail admin
- Monitor CSP violation reports for attempted inline script execution within the admin interface
- Conduct periodic security audits of page content for suspicious patterns that could indicate stored XSS attempts
How to Mitigate CVE-2026-28223
Immediate Actions Required
- Upgrade Wagtail to the patched version appropriate for your release branch: 6.3.8, 7.0.6, 7.2.3, or 7.3.1
- Audit existing page titles in the database for potential XSS payloads and sanitize or remove any suspicious content
- Implement Content Security Policy headers with script-src 'self' to provide defense-in-depth against script injection
Patch Information
Wagtail has released security patches across all supported branches. The fix removes the |safe filter from message rendering in the admin templates, ensuring all user-controlled content is properly HTML-escaped.
| Branch | Patched Version | Release Link |
|---|---|---|
| 6.3.x | 6.3.8 | GitHub Release v6.3.8 |
| 7.0.x | 7.0.6 | GitHub Release v7.0.6 |
| 7.2.x | 7.2.3 | GitHub Release v7.2.3 |
| 7.3.x | 7.3.1 | GitHub Release v7.3.1 |
For complete technical details, refer to the GitHub Security Advisory GHSA-p4v8-rw59-93cq.
Workarounds
- If immediate patching is not possible, disable the wagtail.contrib.simple_translation module by removing it from INSTALLED_APPS until the upgrade can be completed
- Restrict admin access to trusted users only and implement additional authentication controls
- Deploy a WAF with XSS detection rules in front of the Wagtail admin interface as a temporary mitigation
# Upgrade Wagtail using pip (choose the appropriate version for your branch)
pip install --upgrade wagtail==7.3.1
# Or specify in requirements.txt
# wagtail>=7.3.1
# Verify the installed version
pip show wagtail | grep Version
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

