WordPress XML-RPC: A Legacy Interface Almost No One Needs

XML-RPC exposes the site to brute force, pingback DDoS amplification, and ongoing CVEs. Disable it without breaking Jetpack.

XML-RPC is a legacy WordPress remote-control API that lets external clients post articles, manage comments, and run other operations through /xmlrpc.php. In 2026 almost no site actually uses it: the official WordPress mobile app moved to REST in 2018, and Jetpack supports both. Yet the endpoint is still active by default in every WordPress install — and so it remains a favorite attack vector.

Why this matters

Three primary risks: massive brute force through the request-amplification techniques — bypassing typical rate-limiting and compressing an attack into 1% of the time it would take through the login form. Pingback DDoS amplification: attackers abuse the pingback-based amplification techniques. Future vulnerabilities: over the years, several critical CVEs have been found in xmlrpc.php (RCE, type confusion). The code is old, less actively reviewed, and new bugs continue to surface.

How to detect

Reachability check:

curl -I https://example.com/xmlrpc.php

If XML-RPC is active you typically see HTTP/1.1 405 Method Not Allowed (because GET is the wrong verb). Status 200 is also "active". Status 403 or 404 means it is blocked (good). Deeper probe:

curl -X POST -d '<?xml version="1.0"?><methodCall><methodName>system.listMethods</methodName></methodCall>' \
  https://example.com/xmlrpc.php

If it returns a list of methods (wp.getUsersBlogs, request-amplification techniques, ...), XML-RPC is active and exposed.

How to fix

Layer 1 — PHP filter (logical disable only):

// In functions.php or an mu-plugin
add_filter('xmlrpc_enabled', '__return_false');
add_filter('pre_option_enable_xmlrpc', '__return_zero');

This alone is not enough — the file still runs through PHP, every method just refuses. For real protection, block at the web server layer:

<Files xmlrpc.php>
    Require all denied
</Files>
location = /xmlrpc.php {
    deny all;
    access_log off;
    log_not_found off;
}

If you rely on Jetpack and need to keep a specific integration, allow only Jetpack's IP ranges:

<Files xmlrpc.php>
    Require ip 192.0.64.0/18
    Require ip 76.74.255.0/24
</Files>

Common mistakes

Mistake one: enabling only the PHP filter and assuming the site is protected. The file still loads on every request, costs CPU, and a future RCE in xmlrpc.php would still execute. Real protection must be at the web server layer. Mistake two: blocking without checking dependencies. If you use Jetpack in an older configuration, IFTTT integration, or an old version of the WordPress mobile app, blocking will break them. Verify there is no dependency first. Mistake three: blocking only /xmlrpc.php and ignoring ?rest_route=/wp/v2/.... These are separate channels — each needs its own treatment. Mistake four: assuming Wordfence "Login Security" handles it. Wordfence rate-limits the login form, but a request-amplification techniques request counts as a single hit at the WAF layer and slips past.

Verifying the fix

Run curl -I https://example.com/xmlrpc.php — it must return 403 or 404. Run the POST curl from above — it must return 403 or empty, not a method list. If you use Jetpack, open the dashboard > Jetpack > Modules and confirm modules are active. If they show "Connection broken", you need to add Jetpack's IP ranges to the allowlist.

Tip: After blocking, watch the server access log. If XML-RPC was active, you will likely see a big drop in total request volume — much of it was automated brute force you did not even realize was hitting you.