CVE-2026-14488
You're looking at a WordPress plugin vulnerability (CVE-2026-14488) that stems from a single, dangerous mistake: gating nonce verification behind `is_ajax()`. The code in `handle_request()` dispatches the `mbfs_delete` action to the same function regardless of how the request arrives—but AJAX requests get nonce protection while template_redirect requests get nothing. This isn't a missing check; it's a misplaced one that assumed template_redirect requests could never reach this dispatcher. The exploitation path is trivial. The plugin hosts frontend submission forms that are, by design, publicly accessible on any WordPress page where the plugin is installed. An attacker doesn't need to probe for hidden endpoints—they need to find the forms that legitimate users use to submit content, then send a non-AJAX request with the `mbfs_delete` action parameter. Because `is_ajax()` returns false on regular POST/GET requests, the nonce check never fires, and the operation executes without authentication. What makes this worse: `allow_delete` is a configuration option that controls frontend access, but it lives in the config, not in the dispatcher. An admin who disabled frontend deletion entirely may still be vulnerable because the actual authorization check happens at a different layer than the nonce verification. You need to verify both the config setting AND that `handle_request()` applies uniform capability checks regardless of entry point. For your immediate response: audit any plugin where the same sensitive operation is reachable via both admin-ajax.php and frontend hooks. If security controls split based on `is_ajax()`, `is_admin()`, or any context-detection function, you have a context-collision vulnerability. The fix is never to add a check to the unprotected path—it's to move authorization to the dispatcher layer where all paths converge, so every entry point into shared logic gets uniform capability verification.
Reviewed through automated stages and approved by a human before publication.