Vulnerability Types

CSRF in WordPress, Explained

Nonces, why plugins skip them, and how a “moderate” flaw reaches code execution.

Cross-site request forgery makes your browser act against you. The attacker never logs in — they persuade a page you visit to send a request to your site, and your browser dutifully attaches your session.

How WordPress is supposed to prevent it

WordPress issues nonces: short-lived tokens tied to a specific action and user, checked before the action runs. Used correctly, they mean a request that did not originate from your own admin screen fails. The catch is that the check is manual. Every entry point — every admin-post handler, every AJAX action, every REST route — has to verify it. Miss one and that action is forgeable.

Why the class is underrated

CSRF on its own does not steal data or run code. Its severity comes entirely from what the forged action can do. Change a setting: annoying. Import a form definition, write a file, install something: not annoying at all.

Our Ninja Forms disclosure is the example. A missing origin check in front of form-management functionality turned one crafted link, clicked by a logged-in administrator, into a route to code execution.

Assessing a CSRF finding

  1. What action is reachable, and what can it change?
  2. Does it need an administrator, or will any logged-in user do?
  3. How plausibly can the attacker get that person to load a page? For site owners, very plausibly — a support email about their own site.
  4. Is there a second stage? File writes, imports and plugin installation turn CSRF into something else entirely.

Practical defence

  • Patch the plugin.
  • Do not stay permanently logged into WordPress in your everyday browser.
  • Use a separate browser profile for administration.
  • Reduce the number of administrator accounts — every one is a delivery target.

Want this checked automatically across every plugin, theme and core file on your site? WPDeeply Risk Monitor is free.