
Here's a number that should make any site owner uncomfortable: the average WordPress site runs 20 to 30 plugins, and each one can request access to your database, your files, your users' personal data, and outbound network connections. Most administrators install a plugin, click "Activate," and never once ask what that code is actually allowed to touch. That gap between "I installed it" and "I know what it does" is exactly where data leaks are born.
Plugins are the reason WordPress is powerful, and they're also the reason it's the most attacked CMS on the planet. According to multiple vulnerability trackers, the overwhelming majority of WordPress hacks trace back to a plugin or theme, not to WordPress core itself. A single abandoned contact-form plugin with an unpatched flaw can expose every email address, IP, and form submission you've ever collected.
This guide walks you through a practical WordPress plugin permissions audit you can complete in an afternoon. You'll learn how to inventory what you've installed, read the capabilities a plugin actually uses, spot the red flags that signal a leak risk, and build a repeatable review process so your site stays clean six months from now. No hand-waving. Real steps, real file paths, real tradeoffs.
Key Takeaways
- WordPress has no built-in "permissions screen" for plugins, so auditing means inspecting capabilities, database access, file writes, and outbound requests manually or with tooling.
- Start by building a complete plugin inventory, then classify each one by what data it can reach and whether it phones home.
- The biggest leak vectors are plugins that store personal data, make external API calls, or add custom REST/AJAX endpoints without proper capability checks.
- Deactivating is not deleting. Inactive plugins still sit in your file system and remain exploitable.
- Combine a manual quarterly audit with a monitoring layer so you catch new vulnerabilities and unexpected behavior automatically.
- Fewer plugins is almost always safer. If you can't name why a plugin is installed, remove it.
Why WordPress Plugin Permissions Are So Hard to See
If you've used Android or iOS, you're conditioned to expect a permissions prompt: "This app wants access to your camera." WordPress has nothing like that. When you activate a plugin, it inherits the ability to run any PHP code your server allows, query your entire database, read and write files, and open network connections to anywhere on the internet.
WordPress does have a capabilities and roles system, but that controls what users can do, not what plugin code can do. A plugin can call current_user_can() to gate a feature, or it can skip the check entirely. There's no sandbox stopping a plugin from reading your wp_users table and posting it to a remote server.
That means an audit is less about clicking a settings page and more about detective work. You're asking four core questions of every plugin:
- What data can it reach? Which database tables, options, and user records.
- What can it write? Files, uploads, cron jobs, new database rows.
- Does it talk to the outside world? External APIs, analytics, license servers.
- Does it enforce permission checks? Are its endpoints and forms protected by nonces and capability checks?
If that sounds similar to vetting any third-party dependency, it is. The same discipline you'd apply when you vet open-source software for supply chain risks applies here, because a plugin is exactly that: someone else's code running with full trust inside your site.
Step 1: Build a Complete Plugin Inventory
You can't audit what you haven't listed. Before touching any code, produce a full inventory. Here's the fastest reliable way.
- Go to Plugins → Installed Plugins in wp-admin. Note the total count, including inactive ones.
- For each plugin, record: name, version, author, active/inactive status, and last update date (visible on the WordPress.org plugin page).
- Cross-check the file system. Connect via SFTP or your host's file manager and open
/wp-content/plugins/. Every folder here is a plugin, even ones that don't show in wp-admin (a classic sign of a hidden backdoor). - Check for "must-use" plugins in
/wp-content/mu-plugins/. These load automatically and never appear in the standard plugin list.
A worked example
Say you audit a modest business site and find 24 plugins: 18 active, 6 inactive. Of those, 4 haven't been updated by their authors in over two years. Two folders exist on disk that don't appear in wp-admin at all. That's your starting picture, and it already tells you three things:
- The 6 inactive plugins are dead weight and pure risk. Delete them.
- The 4 stale plugins need immediate scrutiny or replacement.
- The 2 mystery folders are urgent. Investigate them before anything else.
If you discover an unexplained folder with obfuscated code, treat it as a live incident and follow a proper response process. Our guide on how to detect and contain an exploited WordPress plugin fast covers exactly what to do next.
Step 2: Classify Each Plugin by Data Sensitivity
Not every plugin carries the same risk. A markdown editor that never touches user data is far less dangerous than a CRM plugin storing names, emails, and payment details. Sort your inventory into tiers so you spend your time where the leak risk is real.
| Risk Tier | Data Reached | External Calls | Example Plugin Types | Audit Priority |
|---|---|---|---|---|
| Critical | User PII, payments, credentials | Frequent | E-commerce, membership, CRM, form builders | Immediate |
| High | Post content, media, options | Sometimes | SEO, backup, migration, page builders | High |
| Medium | Front-end display data | Rare | Sliders, galleries, social feeds | Medium |
| Low | Isolated, no PII | None | Editor tools, admin UI tweaks | Low |
The plugins that both store personal data and make external calls are your top targets. A form builder that emails submissions through a third-party API is precisely the kind of tool that can leak data quietly for months before anyone notices.
Step 3: Inspect What a Plugin Actually Does
Now the detective work. For each Critical and High tier plugin, you want to confirm its behavior against its stated purpose. You don't need to be a senior developer, but you do need to know what to grep for.
Check for external network calls
Search the plugin folder for the functions WordPress uses to make outbound requests. Over SSH:
grep -rn "wp_remote_post\|wp_remote_get\|curl_exec\|file_get_contents" /wp-content/plugins/plugin-name/
Each hit tells you the plugin talks to a server. Now ask: does that make sense? A weather widget calling a weather API is expected. A simple CSS-tweak plugin calling an unknown domain is a red flag. Note every external domain and decide whether you trust it with your data.
Check for database and user access
Search for direct database queries and user data access:
grep -rn "\$wpdb\|get_users\|wp_users\|user_email" /wp-content/plugins/plugin-name/
A plugin reading user_email in bulk deserves an explanation. Legitimate CRMs need it. A decorative plugin does not.
Check that endpoints are protected
Two of the most common WordPress leak patterns are unprotected REST routes and AJAX handlers. Search for endpoint registration:
grep -rn "register_rest_route\|wp_ajax_nopriv\|add_action('wp_ajax" /wp-content/plugins/plugin-name/
The dangerous one is wp_ajax_nopriv_, which registers an action available to logged-out visitors. If a plugin exposes data through a nopriv handler without a capability or nonce check, an attacker can often pull that data with a single crafted request. This is how many "unauthenticated data disclosure" CVEs work.
If you're auditing plugins that were partly AI-generated or forked from generated code, be extra careful here. The habits described in our piece on how to verify AI-generated code before you ship it apply directly, since generated code frequently omits nonce verification and capability checks.
Step 4: Review Roles, Capabilities, and Data Exposure
Some plugins alter your roles and capabilities on install. A membership plugin might add a new role; a poorly written one might grant that role more power than intended. Audit this explicitly.
- Use a role editor or run a quick query to list all roles and their capabilities. Look for any role with
manage_options,edit_users, orupload_filesthat shouldn't have it. - Check your
wp_optionstable for any option storing API keys or tokens in plaintext. Plugins that save credentials unencrypted are a leak waiting to happen if your database is ever dumped. - Review what each plugin exposes in the REST API. Visit
/wp-json/on your site and scan the registered routes. Anything returning user data or private post content without authentication needs locking down. - Confirm that data-collecting plugins respect privacy. Under Tools → Export Personal Data and Erase Personal Data, well-behaved plugins register their data so you can comply with GDPR-style requests.
Before and after: a real cleanup
Take that 24-plugin site. After a full audit, a typical result looks like this:
- Before: 24 plugins, 6 inactive, 2 unknown, 4 stale, 3 making unexplained external calls, 1 nopriv AJAX handler with no nonce.
- After: 14 plugins. Deleted all inactive and stale ones, removed the 2 malicious folders, replaced the leaky form plugin with a maintained alternative, and confirmed the remaining external calls were legitimate license and
Cover image: Innovate Maryland Emerging Technology Center by MDGovpics, licensed under BY 2.0 via Openverse.








