Introduction
A security plugin with over 1 million active WordPress installations just became the attack vector. CVE-2026-8438 is an unauthenticated Stored Cross-Site Scripting vulnerability in the All-In-One Security (AIOS) plugin. The features administrators turn on to harden their sites (REST API restriction and debug logging) are the ones that open a path to arbitrary JavaScript execution in the admin's browser session.
There's some irony in that. AIOS is one of the most widely recommended WordPress security plugins, offering login protection, firewall rules, file integrity monitoring, and audit logging. It carries a 4.7 out of 5 rating on WordPress.org and is developed by Team Updraft, the same team behind the popular UpdraftPlus backup plugin.
Technical Information
CVE-2026-8438 is classified under CWE-79 (Improper Neutralization of Input During Web Page Generation) and carries a CVSS v3.1 score of 7.2 (High) with the vector CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:N. The score reflects that the injection phase needs no authentication and no user interaction, while the impact crosses a security boundary from the attacker's unauthenticated context into the administrator's authenticated browser session.
The vulnerability comes from two separate coding failures that, combined with a specific feature configuration, form a complete Stored XSS attack chain.
Stage 1: Injection via REST API Request Path
When the "Disable REST API for non-logged in users" feature (aiowps_disallow_unauthorized_rest_requests) is enabled, the plugin intercepts REST API requests from unauthenticated users. The get_rest_route() method in wp-security-general-init-tasks.php (around line 887) extracts the REST route from the incoming request. In the fallback code path, it applies urldecode() to $_SERVER['REQUEST_URI'], which decodes URL-encoded payloads into literal HTML characters. For example, %3Cscript%3E becomes <script>. The method then passes the extracted route string straight to the debug logger without sanitizing or validating it.
Stage 2: Unsanitized Storage in the Database
The log_app method in wp-security-debug-logger.php (around line 81) builds a log entry by concatenating a timestamp, the log type, and the user-controlled $info parameter, which holds the unsanitized REST route. When aiowps_enable_debug is enabled, the plugin writes this entry to the WordPress database. Nothing sanitizes, escapes, or validates $info before the write.
Stage 3: Execution via Unescaped Output
When an administrator opens the AIOS Dashboard Debug Logs page, the column_default() method in wp-security-list-debug.php (line 43) retrieves the raw database value and returns it without any escaping. The parent WP_List_Table class then echoes that value directly into the HTML page. Any HTML or JavaScript payload stored in the database renders as executable code in the administrator's browser.
Exploitation Prerequisites
Two plugin features must both be enabled for the vulnerability to be exploitable:
-
aiowps_disallow_unauthorized_rest_requests: The "Disable REST API for non-logged in users" setting must be active. Security-conscious administrators commonly enable it to reduce the WordPress REST API attack surface. -
aiowps_enable_debug: Debug logging must be enabled. It is not on by default, but administrators who are investigating site issues or monitoring for suspicious activity frequently turn it on.
The sites most likely to have both features enabled are the ones run by the most security-conscious administrators. Unfortunately, that means the hardening effort is what increases exposure.
Attack Flow
An unauthenticated attacker sends a crafted HTTP request to the WordPress REST API endpoint with a malicious payload in the URL path. For example, in a request to /wp-json/wp/v2/posts/%3Cscript%3Ealert(document.cookie)%3C/script%3E, urldecode() would turn the URL-encoded portion into <script>alert(document.cookie)</script>. The plugin then logs this decoded, unsanitized value to the database.
When an administrator later views the debug log page, the script runs in their browser session. From there, the attacker's JavaScript can:
- Steal WordPress nonces from the page
- Perform privileged AJAX or REST API actions on behalf of the administrator
- Install malicious plugins or themes
- Create new administrative accounts
- Modify site content or inject further backdoors
The victim does nothing beyond opening a page they would routinely visit as part of their security monitoring.
CVSS Component Breakdown
| Component | Value | Interpretation |
|---|---|---|
| Attack Vector | Network | Exploitable remotely over the internet |
| Attack Complexity | Low | No special conditions beyond feature configuration |
| Privileges Required | None | No authentication needed for injection |
| User Interaction | None | No interaction needed for injection phase |
| Scope | Changed | Impact crosses security boundary to admin session |
| Confidentiality | Low | Attacker can read some admin-accessible data |
| Integrity | Low | Attacker can modify some admin-accessible data |
| Availability | None | No direct availability impact |
The Fix
The fix in changeset 3558989, released in version 5.4.8, addresses both sides of the problem. The column_default() method in wp-security-list-debug.php now wraps the database value in esc_html() before returning it, which converts HTML special characters (<, >, ", &) into their HTML entities. The logging path now also sanitizes data before writing it to the database, as defense in depth. This two-part approach follows the WordPress Coding Standards requirement for "late escaping" at the point of output.
Affected Systems and Versions
- Plugin: All-In-One Security (AIOS) – Security and Firewall for WordPress
- Vulnerable versions: All versions up to and including 5.4.7
- Fixed version: 5.4.8 (released June 3, 2026)
- Minimum WordPress version: 5.0 or higher
- Tested up to: WordPress 7.0
Vulnerable configuration requirements: Both of these settings must be enabled at the same time:
aiowps_disallow_unauthorized_rest_requests("Disable REST API for non-logged in users")aiowps_enable_debug(Debug logging)
Sites running AIOS 5.4.7 or earlier without both features enabled are not exploitable through this specific attack vector.
Vendor Security History
AIOS has had XSS vulnerabilities before. Exploit-DB entry 34854 documents a cross-site scripting vulnerability in version 3.8.3, reported on October 2, 2014, which also let remote attackers inject malicious script code. Taken together, the two make XSS a recurring issue in the plugin's codebase across more than a decade.
The version 5.4.8 changelog credits the discovery to Dmitrii Ignatyev of CleanTalk Inc, stating: "SECURITY: Escaped debug log messages before rendering them in the admin area to prevent a stored XSS vulnerability." Disclosure and patch landed on the same day (June 3, 2026), which shows Team Updraft responded quickly. The root cause, though, is a failure to apply esc_html() to output in admin views, and that is a fundamental secure coding practice that should have been in place from the start.
The Wordfence Intelligence weekly vulnerability report for May 25 to May 31, 2026, listed this patch among 277 vulnerabilities disclosed across 184 plugins and 70 themes in that single reporting period.
References
- NVD: CVE-2026-8438
- Wordfence Advisory: All-In-One Security (AIOS) <= 5.4.7 Unauthenticated Stored XSS
- WordPress Plugin Repository: Changeset 3558989
- AIOS Plugin Page on WordPress.org
- Vulnerable Source: wp-security-list-debug.php (tag 5.4.6, line 43)
- Vulnerable Source: wp-security-debug-logger.php (tag 5.4.6, line 81)
- Vulnerable Source: wp-security-general-init-tasks.php (tag 5.4.6, line 887)
- Vulnerable Source: wp-security-utility.php (tag 5.4.6, line 1547)
- Fixed Source: wp-security-list-debug.php (trunk, line 43)
- Fixed Source: wp-security-debug-logger.php (trunk, line 81)
- Fixed Source: wp-security-general-init-tasks.php (trunk, line 887)
- Fixed Source: wp-security-utility.php (trunk, line 1547)
- Wordfence Intelligence Weekly Report: May 25 to May 31, 2026
- Exploit-DB 34854: Prior AIOS XSS (v3.8.3)
- Wordfence: How To Find XSS Vulnerabilities in WordPress Plugins



