Only the latest minor release receives security fixes.
| Version | Supported |
|---|---|
| 1.3.x | yes |
| 1.2.x | no |
| < 1.2 | no |
If you find a vulnerability, please do not open a public issue.
Email hamzaalinabulsi@gmail.com with:
- a short description of the issue,
- the affected version (output of
wp plugin status np-mcp-builder), - steps to reproduce, and
- whatever proof-of-concept you have.
You can expect a first reply within 72 hours and a fix or mitigation plan within 14 days for confirmed issues. Coordinated disclosure is preferred — once a fix is shipped we will credit the reporter in the release notes unless you ask us not to.
This plugin exposes WordPress functionality as MCP tools. The hostile parties we worry about are:
- Unauthenticated visitors hitting the plugin's MCP endpoints
directly. Mitigated by
permission_callbackon every ability and by themcp-adapterplugin's own auth layer. - Authenticated low-privilege users trying to call abilities that
should require
manage_options. Mitigated by mapping each ability to a real WordPress capability (see the matrix below). - AI clients (Claude, ChatGPT…) that have been instructed by a
malicious prompt. The plugin treats every input as untrusted: all
string inputs go through
sanitize_*/wp_kses_post, all SQL uses$wpdb->prepareor controlledLIKEpatterns, and dangerous operations (np/deactivate-plugin,np/delete-user) refuse to act on the running plugin or current user. - Direct file access to plugin files. Every PHP file checks for
ABSPATHanduninstall.phpchecks forWP_UNINSTALL_PLUGIN.
Each ability is registered with an explicit permission_callback.
The current mapping is:
| Capability | Used by abilities |
|---|---|
manage_options |
site settings, permalinks, maintenance, system info, Yoast global, kit, deactivate self-check |
edit_posts |
post and Elementor read/write, taxonomy assign, SEO audit, get-seo-head |
edit_theme_options |
theme mods, switch theme, kit update, menu management |
manage_categories |
term create/update/delete |
activate_plugins |
list / activate / deactivate plugins |
switch_themes |
list / switch themes |
list_users |
list users |
create_users |
create user |
edit_users |
update user |
delete_users |
delete user (refuses current user) |
upload_files |
image generation |
publish_posts |
post creation |
- All HTTP responses go through
WP_REST_Response/ Abilities API return values; no raw HTML is echoed from ability callbacks. np/deactivate-pluginresolves the running plugin's basename viaplugin_basename( NP_MCP_BUILDER_FILE )and refuses to act on itself, so the operator cannot accidentally lock themselves out.np/delete-userreadsget_current_user_id()and refuses to delete that ID.- The maintenance-mode handler runs at
template_redirectpriority 0, exits with503and aRetry-Afterheader, but skips the request entirely whenWP_CLIis defined or the URI starts with/wp-adminor/wp-loginso the operator can always recover. - The single direct database call (transient purge in
np/clear-cache) uses two fixedLIKEpatterns; user input never reaches the SQL. - The Gemini API key is stored in the standard
wp_optionstable through the Settings API; it is never echoed back in any response or admin field withvalue=.
The repo ships its own audit harness at
bin/audit-security.sh. To reproduce locally:
bash bin/audit-security.shIt runs:
WordPressPHPCS standard, security sniffs only.PHPCompatibilityWPagainst PHP 8.0+.- Hand-rolled grep checks for dangerous functions, raw superglobals,
missing
ABSPATHguards, hard-coded secrets. - A pass that confirms every
wp_register_abilitycall has apermission_callback.
The latest run is summarised in
docs/SECURITY-AUDIT.md.