CVE-2025-31385 Overview
CVE-2025-31385 is a Cross-Site Request Forgery (CSRF) vulnerability in the WordPress plugin Site Table of Contents by intelcaprep. The flaw affects all versions through 0.3 and enables an attacker to trigger Stored Cross-Site Scripting (XSS) when an authenticated administrator visits a crafted page. The issue is tracked under CWE-352 and stems from missing CSRF protections on plugin actions that persist user-controlled input. Successful exploitation injects attacker-controlled JavaScript into pages rendered by the plugin, impacting confidentiality, integrity, and availability of the affected site.
Critical Impact
A remote, unauthenticated attacker can coerce an authenticated administrator into submitting a forged request that stores malicious JavaScript, leading to persistent XSS execution in administrator and visitor browsers.
Affected Products
- WordPress plugin Site Table of Contents (site-table-of-contents) by intelcaprep
- All versions from initial release through 0.3
- WordPress sites running the plugin with administrator users reachable by browser-based phishing
Discovery Timeline
- 2025-04-09 - CVE-2025-31385 published to NVD
- 2026-04-23 - Last updated in NVD database
Technical Details for CVE-2025-31385
Vulnerability Analysis
The plugin exposes state-changing actions that update Table of Contents configuration or content without verifying a valid anti-CSRF token. WordPress provides the wp_nonce_field() and check_admin_referer() primitives for exactly this purpose, but the affected handlers do not enforce them. As a result, any authenticated administrator who visits an attacker-controlled page can be silently coerced into submitting a request that saves attacker-supplied input into the plugin's persistent storage.
Because the stored input is later rendered without sufficient output encoding, the attack chains into Stored XSS. The injected payload executes in the browser context of every visitor who loads an affected page, including other administrators. This expands the impact from a single forged action into persistent JavaScript execution across the site.
The attack requires user interaction, since the administrator must visit the attacker's page while authenticated to the WordPress dashboard. No prior privileges are required for the attacker, which is why the vulnerability is exploitable from the network. EPSS currently rates the probability of exploitation as low, but the prevalence of WordPress phishing campaigns makes the attack pattern realistic.
Root Cause
The root cause is the absence of CSRF token validation on plugin endpoints that persist user-supplied data, combined with insufficient output escaping when that data is later rendered. The Site Table of Contents plugin should call check_admin_referer() or wp_verify_nonce() on every privileged request and apply esc_html(), esc_attr(), or wp_kses_post() on output.
Attack Vector
An attacker hosts a malicious page or sends a crafted link to a WordPress administrator. When the administrator visits the page while logged in, the browser auto-submits a forged POST request to the plugin's settings endpoint. The request stores attacker-controlled JavaScript in the plugin configuration. Subsequent renders of the affected component execute the payload in the victim's browser session. See the Patchstack WordPress Vulnerability Report for the technical advisory.
No verified proof-of-concept code is published. The vulnerability mechanism is described in prose because no validated exploit sample exists in the referenced advisory.
Detection Methods for CVE-2025-31385
Indicators of Compromise
- Unexpected <script>, onerror, or onload content stored in wp_options rows associated with site_toc or similar plugin option keys
- Outbound requests from administrator browsers to unfamiliar domains immediately after visiting WordPress admin pages
- New or modified posts and Table of Contents entries containing HTML event handlers or encoded JavaScript
- Plugin configuration changes in WordPress audit logs without a corresponding administrator action
Detection Strategies
- Inspect plugin-managed database rows for HTML tags and JavaScript URI schemes such as javascript:, data:text/html, and javascript
- Monitor HTTP referer headers on plugin admin-post and admin-ajax.php endpoints for cross-origin sources
- Alert on WordPress administrator sessions that submit plugin settings requests without a preceding GET of the settings page
Monitoring Recommendations
- Enable WordPress activity logging plugins to record administrator option changes with user, IP, and referer fields
- Forward web server access logs to a central analytics platform and flag POSTs to plugin endpoints lacking same-origin referers
- Add Content Security Policy (CSP) reporting to capture inline script execution attempts on public pages
How to Mitigate CVE-2025-31385
Immediate Actions Required
- Deactivate and remove the Site Table of Contents plugin until a patched version is available
- Audit plugin options and post content for injected scripts and revert tampered entries
- Force a password reset and session invalidation for all WordPress administrators
- Restrict /wp-admin/ access to known IP ranges using web server rules or a Web Application Firewall (WAF)
Patch Information
No fixed version is identified in the advisory. The vulnerability affects Site Table of Contents from initial release through <= 0.3. Monitor the Patchstack advisory and the WordPress plugin repository for an updated release that adds nonce validation and output escaping.
Workarounds
- Replace the plugin with an actively maintained Table of Contents alternative that enforces nonces and escapes output
- Deploy a WAF rule that blocks POST requests to plugin endpoints lacking a same-origin Referer and a valid WordPress nonce parameter
- Enforce a strict Content Security Policy that disallows inline scripts on pages rendered by the plugin
- Require administrators to use a separate browser profile or session for WordPress administration to reduce CSRF exposure
# Apache example: block cross-origin POSTs to plugin admin endpoints
<LocationMatch "/wp-admin/(admin-post|admin-ajax)\.php">
SetEnvIfNoCase Referer "^https?://your-site\.example/" same_origin
<RequireAll>
Require method GET
Require env same_origin
</RequireAll>
</LocationMatch>
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.


