WordPress Plugins and Themes Vulnerabilities: Stats, Facts and Recommendations.

For the past 30 months, we have reported and then disclosed on this blog quite a lot of vulnerabilities we discovered in WordPress themes and plugins. Here are below some interesting stats and facts about them, as well as a few recommendations for all developers of WordPress plugins and themes.

Vulnerabilities Summary

Discovered and reported vulnerabilities: 249
Vulnerable plugins and themes: 190 (167 plugins, 23 themes).
Total active installations: 12.2+ million.

Vulnerability Severity Levels and Types

Improper Access Control was clearly the biggest issue we found among those vulnerabilities. Each time, the developers didn’t check the user capability, which always leads to devastating consequences: an unauthenticated user can change the WordPress core options, import the plugin or theme settings, create admin accounts or redirect the blog to a malicious website among other joys.

Vulnerable Entry Points

It is not a big surprise that the entry point is the WordPress API because it handles authentication, capabilities and roles, security nonces and all the things that are required to restrict access to the CMS. I stress that the problem is not the WordPress API, but the way it is misused by developers.

WordPress API Entry Points

Both the AJAX API and the admin_init hook were the most misused by developers.

Avoidable or Unavoidable?

Let’s see how many vulnerabilities could have been avoided if the developers took only one minute (or sometime less) of their time to read the online WordPress API documentation of the function or hook they misused in their code:

68% of all reported vulnerabilities could have been avoided very easily by reading the documentation. For instance, here’s the documentation of the admin_init hook:

Fires as an admin screen or script is being initialized.
Note, this does not just run on user-facing admin screens. It runs on admin-ajax.php and admin-post.php as well.
This is roughly analogous to the more general ‘init’ hook, which fires earlier.

As we can see, it takes a few seconds to read and understand that this hook can be triggered by any user, logged-in or not, and thus it’s important to check that the user triggering it has the right capability.


If you’re a developer of themes or plugins for WordPress, here’s a non-exhaustive list of recommendations:

  • Make sure to always ask yourself the following question, whenever you start coding a new function/method or class: Who should be allowed to access it?
  • Make sure the user has the right capability.
  • Add security nonces to protect against CSRF attacks (don’t use them for authentication, it’s not their job).
  • Validate all user input. WordPress has a lot of data sanitization functions, maybe a bit too many as I’ve seen several developers very confused about which one they should use, or using the wrong one. If that happened to you, know that the good old PHP htmlspecialchars and htmlentities will often do a great job. The strip_tags and filter_var functions come in handy too.
  • Don’t try to manage file uploads yourself: use the WordPress API instead, it has functions to safely handle that.
  • Use prepare for your SQL queries to prevent SQL injection attacks.

Note that simply following those 6 points would have avoided 100% of the above vulnerabilities.

Stay informed about the latest vulnerabilities