{"id":1154,"date":"2026-08-20T18:34:21","date_gmt":"2026-08-20T18:34:21","guid":{"rendered":"https:\/\/www.ahosting.net\/blog\/?p=1154"},"modified":"2026-08-21T16:44:30","modified_gmt":"2026-08-21T16:44:30","slug":"stop-rest-api-user-enumeration","status":"publish","type":"post","link":"https:\/\/www.ahosting.net\/blog\/stop-rest-api-user-enumeration\/","title":{"rendered":"Stop REST API User Enumeration in WordPress (2026)"},"content":{"rendered":"\n<script type=\"application\/ld+json\">{\"@context\": \"https:\/\/schema.org\", \"@type\": \"FAQPage\", \"mainEntity\": [{\"@type\": \"Question\", \"name\": \"How do I turn off the REST API in WordPress without breaking Gutenberg in 2026?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"Specifically, do not turn the whole REST API off. Gate only the two users routes behind a capability check with the rest_endpoints filter, which leaves every other route reachable. Gutenberg, WooCommerce admin screens, and the WordPress 7.0 ability endpoints all keep working because their requests carry an authenticated session. A site-wide authentication block is the version of this fix that breaks the editor, and the blast-radius table earlier in this guide shows exactly which six surfaces it takes down.\"}}, {\"@type\": \"Question\", \"name\": \"rest_endpoints vs rest_authentication_errors: which filter should I use to stop REST API user enumeration?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"Therefore the answer depends on scope. The rest_endpoints filter edits the route table itself, so it can target the users collection and single-user routes and leave everything else alone. The rest_authentication_errors filter sits in front of every route at once, which makes it a blunt instrument for this job. Use rest_endpoints with a permission callback for enumeration, and reserve rest_authentication_errors for genuinely private installations where no route should answer an anonymous request.\"}}, {\"@type\": \"Question\", \"name\": \"Does WordPress 7.0 expose more user data through the wp-abilities\/v1 namespace in 2026?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"Notably, it adds a second REST namespace rather than more public user data. WordPress 6.9 introduced the Abilities API and WordPress 7.0 shipped its JavaScript client, registering a small core set covering site, environment, and current-user information under wp-abilities\/v1. Those abilities run permission callbacks of their own, so they are not an anonymous disclosure route. The practical consequence is different: a blanket authentication block now silently disables agent and AI-client discovery as well.\"}}, {\"@type\": \"Question\", \"name\": \"Should I stop REST API user enumeration on an AHosting reseller account hosting 30 client sites?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"Ultimately yes, and the reseller case is the strongest one. Every client site under a reseller account publishes its own author list, so a single scripted pass across 30 domains returns 30 username sets from one afternoon of work. Deploy the same mu-plugin file to each account rather than editing 30 themes, because a theme switch on any one site silently reopens the door. The exposure matrix in this guide lists the four vectors each deployment has to close.\"}}, {\"@type\": \"Question\", \"name\": \"Why does my security scanner still report CVE-2017-5487 on a fully patched WordPress 7.0 site?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"In fact, that finding is almost always a misattribution. CVE-2017-5487 was fixed in WordPress 4.7.1 in January 2017, which narrowed the users endpoint to authors of post types that opt into REST. What your scanner detects today is the remaining intended behavior, not the unpatched flaw, and several scanner templates simply map any reachable users route to the old identifier. Treat it as a configuration finding to decide on, never as evidence of an unpatched core.\"}}, {\"@type\": \"Question\", \"name\": \"Author archive redirect vs REST endpoint restriction: which closes more username exposure?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"By contrast with the common assumption, neither one closes the exposure alone. The REST restriction shuts the route most scanners probe first, while the author redirect shuts the oldest vector, the numeric author query that resolves to a slug in the URL. Two further doors stay open behind both of them, namely the core users sitemap and the oEmbed response. Closing any single door moves the attacker to the next one rather than stopping the collection.\"}}, {\"@type\": \"Question\", \"name\": \"Can an mu-plugin stop REST API user enumeration on AHosting WordPress hosting in 2026?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"Fortunately yes, and an mu-plugin is the right delivery method on any cPanel account. Files placed in wp-content\/mu-plugins load automatically, cannot be deactivated from the dashboard, and survive both theme changes and core updates, which is where functions.php edits usually fail. Create the directory through the cPanel File Manager if it does not exist yet, then upload a single PHP file containing all four fixes. No support ticket and no server-level change is required.\"}}, {\"@type\": \"Question\", \"name\": \"What happens if I stop REST API user enumeration on a headless WordPress site using the users endpoint?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"Consequently, a headless front end that renders author bylines from the users route will start receiving empty responses. Handle it by exempting a specific application password or by embedding author data in the posts response with the _embed parameter instead of a separate users call. Test the front end against a staging copy before deploying, because the failure is a missing byline rather than a visible error, and that is easy to ship without noticing.\"}}, {\"@type\": \"Question\", \"name\": \"What is the AHosting Username Exposure Matrix and which four vectors does it cover?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"Similarly to a pre-flight checklist, it is a four-row reference that maps every core route that publishes an author slug against the fix that closes it. The four vectors are the REST users routes, the numeric author query redirect, the core users sitemap added in WordPress 5.5, and the oEmbed embed endpoint. Each row also records what remains reachable if you close only the REST route, which is the mistake most published guides encourage.\"}}, {\"@type\": \"Question\", \"name\": \"Does a dedicated IP address help stop REST API user enumeration attempts before they reach WordPress?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"Interestingly, a dedicated IP changes reputation rather than reachability. Enumeration probes target your domain, so they arrive whichever address answers, and the request still reaches PHP because these routes are never served from cache. What a dedicated IP does change is that your address carries no other tenant's history, so firewall reputation decisions about your traffic reflect only your own site. Isolation and the application-layer fix solve different halves of the problem.\"}}]}<\/script>\n\n\n<div class=\"wp-block-aioseo-table-of-contents\"><ul><li><a class=\"aioseo-toc-item\" href=\"#what-enumeration-exposes\">What REST API User Enumeration Exposes on a WordPress Site in 2026<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#scanner-cve-misattribution\">Why Your Scanner Reports a 2017 CVE on a Patched WordPress 7.0 Site<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#four-doors\">The Four Doors That Leak Author Slugs Before You Stop REST API User Enumeration<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#how-to-fix\">How to Stop REST API User Enumeration Without Breaking the Block Editor<\/a><ul><li><a class=\"aioseo-toc-item\" href=\"#gate-users-routes\">First, Gate the Users Routes by Capability<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#close-author-redirect\">Next, Close the Author Archive Redirect<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#drop-users-sitemap\">Then, Drop the Users Sitemap Provider<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#strip-oembed-author\">Finally, Strip Author Fields From oEmbed<\/a><\/li><\/ul><\/li><li><a class=\"aioseo-toc-item\" href=\"#blast-radius\">Blast Radius: What Each Way to Stop REST API User Enumeration Breaks<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#wordpress-7-abilities\">WordPress 7.0 Changed the Cost of Blocking REST Traffic Site-Wide<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#exposure-checker\">Check Your Own Exposure Before You Stop REST API User Enumeration<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#hosting-context\">Where Hosting Sits: Server-Level Context on AHosting WordPress Hosting<\/a><ul><li><a class=\"aioseo-toc-item\" href=\"#cost-of-leaving-it-open\">What It Costs to Leave REST API User Enumeration Open<\/a><\/li><\/ul><\/li><li><a class=\"aioseo-toc-item\" href=\"#checklist\">A Checklist to Stop REST API User Enumeration and Keep It Closed<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#faq-stop-rest-api-user-enumeration\">Frequently Asked Questions: Stop REST API User Enumeration<\/a><ul><li><a class=\"aioseo-toc-item\" href=\"#faq-turn-off-rest-api-gutenberg\">How do I turn off the REST API in WordPress without breaking Gutenberg in 2026?<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#faq-rest-endpoints-vs-authentication-errors\">rest_endpoints vs rest_authentication_errors: which filter should I use to stop REST API user enumeration?<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#faq-wp-abilities-namespace-2026\">Does WordPress 7.0 expose more user data through the wp-abilities\/v1 namespace in 2026?<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#faq-reseller-thirty-client-sites\">Should I stop REST API user enumeration on an AHosting reseller account hosting 30 client sites?<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#faq-scanner-reports-cve-2017-5487\">Why does my security scanner still report CVE-2017-5487 on a fully patched WordPress 7.0 site?<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#faq-author-archive-vs-rest-restriction\">Author archive redirect vs REST endpoint restriction: which closes more username exposure?<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#faq-mu-plugin-ahosting-2026\">Can an mu-plugin stop REST API user enumeration on AHosting WordPress hosting in 2026?<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#faq-headless-users-endpoint\">What happens if I stop REST API user enumeration on a headless WordPress site using the users endpoint?<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#faq-username-exposure-matrix\">What is the AHosting Username Exposure Matrix and which four vectors does it cover?<\/a><\/li><li><a class=\"aioseo-toc-item\" href=\"#faq-dedicated-ip-enumeration-attempts\">Does a dedicated IP address help stop REST API user enumeration attempts before they reach WordPress?<\/a><\/li><\/ul><\/li><\/ul><\/div>\n\n\n<div class=\"ah-tldr\">\n  <span class=\"ah-tldr-badge\">TL;DR<\/span>\n  <p>To stop REST API user enumeration, gate the users routes by capability in an mu-plugin, then close the author redirect, the users sitemap, and the oEmbed author fields. Verify all four while logged out.<\/p>\n<\/div>\n\n\n\n<p class=\"wp-block-paragraph\">You can stop REST API user enumeration on a WordPress site in about ten minutes. The complication is that most of the code circulating for this job either breaks the block editor or, since WordPress 7.0, quietly disables a surface you may not know you are running.<\/p>\n\n\n\n<figure class=\"wp-block-audio\"><audio controls src=\"https:\/\/www.ahosting.net\/blog\/wp-content\/uploads\/2026\/08\/Block_User_Enumeration_Without_Breaking_WordPress.m4a\"><\/audio><figcaption class=\"wp-element-caption\">Listen: why closing the REST users route alone still leaves three doors publishing the same author slugs. By Matt Chrust, Director of Business Development, AHosting.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">This guide separates the four routes that publish author information, gives one mu-plugin that closes all of them, and shows what each competing method to stop REST API user enumeration actually costs you. Notably, it also explains why a clean vulnerability scan is not what you are aiming for here.<\/p>\n\n\n\n<h2 id=\"what-enumeration-exposes\" class=\"wp-block-heading\">What REST API User Enumeration Exposes on a WordPress Site in 2026<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Before you can stop REST API user enumeration you need to know what it discloses, and the honest answer is narrower than most guides claim. Enumeration is reconnaissance, not intrusion. A request to the users collection returns every account that has authored a published post in a post type that opts into REST, and the response carries an ID, a display name, an author slug, an avatar URL, and a link to the author archive.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Precision matters here, because most write-ups overstate it. The public response exposes the author slug, stored as user_nicename, and not the login name. Per the <a href=\"https:\/\/developer.wordpress.org\/rest-api\/reference\/users\/\" target=\"_blank\" rel=\"noopener\">REST API users reference<\/a>, the login name appears only in the authenticated edit context. However, WordPress seeds the slug from the login name when an account is created, so unless someone deliberately changed it afterwards the two match. On the majority of installations, therefore, the slug is the login name in practice.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That distinction decides how seriously to treat the finding. Half of a login pair is not a breach, but it is a permanent advantage handed to whoever asks. The <a href=\"https:\/\/owasp.org\/www-project-web-security-testing-guide\/stable\/4-Web_Application_Security_Testing\/03-Identity_Management_Testing\/04-Testing_for_Account_Enumeration_and_Guessable_User_Account.html\" target=\"_blank\" rel=\"noopener\">OWASP Web Security Testing Guide entry on account enumeration<\/a> classifies this as an identity-management weakness precisely because it converts blind guessing into targeted guessing. Furthermore, the NIST guidance on memorized secrets in <a href=\"https:\/\/pages.nist.gov\/800-63-4\/sp800-63b.html\" target=\"_blank\" rel=\"noopener\">SP 800-63B<\/a> assumes the password carries the authentication weight, which is exactly the assumption that weakens when the other half is published.<\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<iframe loading=\"lazy\" title=\"Stop REST API User Enumeration in WordPress (2026 Fix)\" width=\"500\" height=\"281\" src=\"https:\/\/www.youtube-nocookie.com\/embed\/SHfv0CX3Dy8?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe>\n<\/div><\/figure>\n\n\n\n<h2 id=\"scanner-cve-misattribution\" class=\"wp-block-heading\">Why Your Scanner Reports a 2017 CVE on a Patched WordPress 7.0 Site<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">If a vulnerability scan flagged this and sent you here, read this section before you change anything. The finding is usually a misattribution rather than an unpatched core.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/nvd.nist.gov\/vuln\/detail\/CVE-2017-5487\" target=\"_blank\" rel=\"noopener\">CVE-2017-5487<\/a> describes a flaw in WordPress 4.7 that was fixed in 4.7.1 in January 2017. In 4.7.0 the users endpoint returned authors of any public post type. The 4.7.1 release narrowed that to post types which explicitly declare they should appear in REST, which is the behavior every modern release ships.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Consequently, what a scanner detects on WordPress 7.0 today is the remaining intended behavior, not the old defect. Several scanner templates map any reachable users route to that 2017 identifier, and at least one open-source template project has removed the CVE tag for this reason. In practice you should treat the alert as a configuration decision with a real security rationale, and never as evidence that core is out of date. The difference matters when you are reporting to a client, because promising to patch a CVE that was fixed nine years ago is a promise you cannot keep.<\/p>\n\n\n\n<h2 id=\"four-doors\" class=\"wp-block-heading\">The Four Doors That Leak Author Slugs Before You Stop REST API User Enumeration<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The REST route is the one scanners probe first, which is why it collects the attention. It is not the only one. Three further core features publish the same author slugs by different means, and closing the REST route alone simply moves the collection to whichever door is still open.<\/p>\n\n\n\n<figure class=\"wp-block-table ah-ladder\"><table><thead><tr><th>Door<\/th><th>Anonymous request<\/th><th>What it returns<\/th><th>Closed by<\/th><th>Open after a REST-only fix<\/th><\/tr><\/thead><tbody><tr><td>1. REST users routes<\/td><td>\/wp-json\/wp\/v2\/users<\/td><td>ID, display name, author slug, avatar, archive link<\/td><td>Capability gate via rest_endpoints<\/td><td>No<\/td><\/tr><tr><td>2. Author query redirect<\/td><td>\/?author=1<\/td><td>A 301 to \/author\/slug\/, printing the slug in the URL<\/td><td>template_redirect guard or a rewrite rule<\/td><td>Yes<\/td><\/tr><tr><td>3. Core users sitemap<\/td><td>\/wp-sitemap-users-1.xml<\/td><td>Every author archive URL on the site<\/td><td>wp_sitemaps_add_provider filter<\/td><td>Yes<\/td><\/tr><tr><td>4. oEmbed endpoint<\/td><td>\/wp-json\/oembed\/1.0\/embed?url=<\/td><td>author_name and author_url for any public post<\/td><td>oembed_response_data filter<\/td><td>Yes<\/td><\/tr><\/tbody><\/table><figcaption class=\"wp-element-caption\">The AHosting Username Exposure Matrix: the four core routes that publish author slugs, the fix that closes each, and which remain reachable if you close only the REST route.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The users sitemap is the one that surprises people, because it arrived quietly with automatic sitemaps in WordPress 5.5 and is enabled by default. Agencies feel the combined effect hardest. An account running many client installations publishes a separate author list per domain, so <a href=\"https:\/\/www.ahosting.net\/reseller-hosting.html\">reseller hosting environments<\/a> need the same four fixes deployed uniformly rather than site by site.<\/p>\n\n\n\n<div class=\"ah-infographic\">\n<svg viewBox=\"0 0 1200 620\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" role=\"img\" aria-label=\"Four WordPress routes that publish author slugs feed one username list, which feeds credential stuffing against the login endpoint and consumes entry processes.\">\n<title>The four doors that leak WordPress author slugs<\/title>\n<desc>Four core routes publish author slugs: the REST users routes, the numeric author query redirect, the core users sitemap, and the oEmbed endpoint. All four feed a single username list, which is then used for credential stuffing against the login endpoint, consuming entry processes on shared hosting.<\/desc>\n<rect width=\"1200\" height=\"620\" fill=\"#0f172a\"\/>\n<rect x=\"0\" y=\"0\" width=\"10\" height=\"620\" fill=\"#2563eb\"\/>\n<text x=\"52\" y=\"60\" font-family=\"Poppins,Arial,sans-serif\" font-size=\"30\" font-weight=\"700\" fill=\"#ffffff\">Four doors, one username list<\/text>\n<text x=\"52\" y=\"94\" font-family=\"Poppins,Arial,sans-serif\" font-size=\"18\" fill=\"#94a3b8\">Closing only the REST route leaves three routes returning the same author slugs<\/text>\n<rect x=\"52\" y=\"132\" width=\"330\" height=\"86\" rx=\"8\" fill=\"#1e293b\" stroke=\"#334155\"\/>\n<text x=\"72\" y=\"164\" font-family=\"Poppins,Arial,sans-serif\" font-size=\"17\" font-weight=\"700\" fill=\"#60a5fa\">Door 1<\/text>\n<text x=\"72\" y=\"192\" font-family=\"Poppins,Arial,sans-serif\" font-size=\"16\" fill=\"#e2e8f0\">\/wp-json\/wp\/v2\/users<\/text>\n<rect x=\"52\" y=\"240\" width=\"330\" height=\"86\" rx=\"8\" fill=\"#1e293b\" stroke=\"#334155\"\/>\n<text x=\"72\" y=\"272\" font-family=\"Poppins,Arial,sans-serif\" font-size=\"17\" font-weight=\"700\" fill=\"#60a5fa\">Door 2<\/text>\n<text x=\"72\" y=\"300\" font-family=\"Poppins,Arial,sans-serif\" font-size=\"16\" fill=\"#e2e8f0\">\/?author=1 redirect<\/text>\n<rect x=\"52\" y=\"348\" width=\"330\" height=\"86\" rx=\"8\" fill=\"#1e293b\" stroke=\"#334155\"\/>\n<text x=\"72\" y=\"380\" font-family=\"Poppins,Arial,sans-serif\" font-size=\"17\" font-weight=\"700\" fill=\"#60a5fa\">Door 3<\/text>\n<text x=\"72\" y=\"408\" font-family=\"Poppins,Arial,sans-serif\" font-size=\"16\" fill=\"#e2e8f0\">\/wp-sitemap-users-1.xml<\/text>\n<rect x=\"52\" y=\"456\" width=\"330\" height=\"86\" rx=\"8\" fill=\"#1e293b\" stroke=\"#334155\"\/>\n<text x=\"72\" y=\"488\" font-family=\"Poppins,Arial,sans-serif\" font-size=\"17\" font-weight=\"700\" fill=\"#60a5fa\">Door 4<\/text>\n<text x=\"72\" y=\"516\" font-family=\"Poppins,Arial,sans-serif\" font-size=\"16\" fill=\"#e2e8f0\">oembed\/1.0\/embed<\/text>\n<path d=\"M400 175 L470 175 L470 320 L520 320\" stroke=\"#475569\" stroke-width=\"2\" fill=\"none\"\/>\n<path d=\"M400 283 L470 283 L470 320 L520 320\" stroke=\"#475569\" stroke-width=\"2\" fill=\"none\"\/>\n<path d=\"M400 391 L470 391 L470 320 L520 320\" stroke=\"#475569\" stroke-width=\"2\" fill=\"none\"\/>\n<path d=\"M400 499 L470 499 L470 320 L520 320\" stroke=\"#475569\" stroke-width=\"2\" fill=\"none\"\/>\n<rect x=\"524\" y=\"262\" width=\"250\" height=\"116\" rx=\"8\" fill=\"#1e293b\" stroke=\"#2563eb\" stroke-width=\"2\"\/>\n<text x=\"548\" y=\"300\" font-family=\"Poppins,Arial,sans-serif\" font-size=\"17\" font-weight=\"700\" fill=\"#ffffff\">Author slug list<\/text>\n<text x=\"548\" y=\"328\" font-family=\"Poppins,Arial,sans-serif\" font-size=\"15\" fill=\"#cbd5e1\">user_nicename, which on<\/text>\n<text x=\"548\" y=\"350\" font-family=\"Poppins,Arial,sans-serif\" font-size=\"15\" fill=\"#cbd5e1\">default installs matches login<\/text>\n<path d=\"M778 320 L830 320\" stroke=\"#475569\" stroke-width=\"2\" fill=\"none\"\/>\n<rect x=\"834\" y=\"200\" width=\"314\" height=\"106\" rx=\"8\" fill=\"#1e293b\" stroke=\"#334155\"\/>\n<text x=\"858\" y=\"238\" font-family=\"Poppins,Arial,sans-serif\" font-size=\"17\" font-weight=\"700\" fill=\"#f87171\">Credential stuffing<\/text>\n<text x=\"858\" y=\"266\" font-family=\"Poppins,Arial,sans-serif\" font-size=\"15\" fill=\"#cbd5e1\">Half the login pair is now known<\/text>\n<text x=\"858\" y=\"288\" font-family=\"Poppins,Arial,sans-serif\" font-size=\"15\" fill=\"#cbd5e1\">before the first password guess<\/text>\n<rect x=\"834\" y=\"330\" width=\"314\" height=\"106\" rx=\"8\" fill=\"#1e293b\" stroke=\"#334155\"\/>\n<text x=\"858\" y=\"368\" font-family=\"Poppins,Arial,sans-serif\" font-size=\"17\" font-weight=\"700\" fill=\"#fbbf24\">Entry process cost<\/text>\n<text x=\"858\" y=\"396\" font-family=\"Poppins,Arial,sans-serif\" font-size=\"15\" fill=\"#cbd5e1\">Probes bypass cache entirely and<\/text>\n<text x=\"858\" y=\"418\" font-family=\"Poppins,Arial,sans-serif\" font-size=\"15\" fill=\"#cbd5e1\">consume one PHP slot per request<\/text>\n<text x=\"52\" y=\"586\" font-family=\"Poppins,Arial,sans-serif\" font-size=\"15\" fill=\"#64748b\">AHosting.net  |  Est. 2002<\/text>\n<\/svg>\n<\/div>\n\n\n\n<h2 id=\"how-to-fix\" class=\"wp-block-heading\">How to Stop REST API User Enumeration Without Breaking the Block Editor<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">To stop REST API user enumeration without breaking anything, restrict the two users routes behind a capability check rather than removing them, and close the other three doors in the same file.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Deliver all four fixes as a single must-use plugin. Create wp-content\/mu-plugins if it does not exist, then upload one PHP file. Files there load automatically, cannot be deactivated from the dashboard, and survive theme switches and core updates, which is where the usual functions.php advice fails.<\/p>\n\n\n\n<h3 id=\"gate-users-routes\" class=\"wp-block-heading\">First, Gate the Users Routes by Capability<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The rest_endpoints filter edits the route table before dispatch. Rather than unsetting the routes, replace the permission callback so the routes still exist but answer only to a request that can list users.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\n\/* Plugin Name: AHosting Author Slug Hardening *\/\n\nadd_filter( 'rest_endpoints', function ( $endpoints ) {\n    $routes = array( '\/wp\/v2\/users', '\/wp\/v2\/users\/(?P&lt;id&gt;&#91;\\d]+)' );\n    foreach ( $routes as $route ) {\n        if ( ! isset( $endpoints&#91; $route ] ) ) {\n            continue;\n        }\n        foreach ( $endpoints&#91; $route ] as $i =&gt; $handler ) {\n            if ( ! isset( $handler&#91;'methods'] ) ) {\n                continue;\n            }\n            if ( false === strpos( $handler&#91;'methods'], 'GET' ) ) {\n                continue;\n            }\n            $endpoints&#91; $route ]&#91; $i ]&#91;'permission_callback'] = function () {\n                return current_user_can( 'list_users' );\n            };\n        }\n    }\n    return $endpoints;\n} );<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">An anonymous request now receives a 401 while an editor session continues to populate the author dropdown. By contrast, the widely copied unset approach deletes the route for everyone, including administrators.<\/p>\n\n\n\n<h3 id=\"close-author-redirect\" class=\"wp-block-heading\">Next, Close the Author Archive Redirect<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The numeric author query is the oldest vector and predates REST entirely. Catch it early and send the visitor to the homepage.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>add_action( 'template_redirect', function () {\n    if ( is_admin() ) {\n        return;\n    }\n    if ( ! isset( $_GET&#91;'author'] ) ) {\n        return;\n    }\n    wp_safe_redirect( home_url( '\/' ), 301 );\n    exit;\n} );<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Sites that genuinely publish author archives for readers should skip this one and accept the exposure knowingly. That is a legitimate editorial trade-off rather than an oversight.<\/p>\n\n\n\n<h3 id=\"drop-users-sitemap\" class=\"wp-block-heading\">Then, Drop the Users Sitemap Provider<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Core registers a users provider inside its automatic sitemap index. Returning false for that provider removes the file and its index entry together.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>add_filter( 'wp_sitemaps_add_provider', function ( $provider, $name ) {\n    if ( 'users' === $name ) {\n        return false;\n    }\n    return $provider;\n}, 10, 2 );<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Verify afterwards that the sitemap index no longer references the users file, because a cached index will keep advertising a path that now returns a 404.<\/p>\n\n\n\n<h3 id=\"strip-oembed-author\" class=\"wp-block-heading\">Finally, Strip Author Fields From oEmbed<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The embed endpoint answers for any public post URL and includes the author name and archive link in its response.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>add_filter( 'oembed_response_data', function ( $data ) {\n    unset( $data&#91;'author_name'] );\n    unset( $data&#91;'author_url'] );\n    return $data;\n} );<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Embedding your posts elsewhere continues to work; the embed card simply loses its byline. Additionally, if you never want other sites discovering embeds at all, remove the discovery links from the document head as a separate decision.<\/p>\n\n\n\n<h2 id=\"blast-radius\" class=\"wp-block-heading\">Blast Radius: What Each Way to Stop REST API User Enumeration Breaks<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Three methods circulate for this problem and they are not interchangeable. The table below scores each against the surfaces a live site actually depends on, which is the comparison the published snippets leave out.<\/p>\n\n\n\n<figure class=\"wp-block-table ah-ladder\"><table><thead><tr><th>Surface<\/th><th>Unset the routes<\/th><th>Block all anonymous REST<\/th><th>Capability gate (recommended)<\/th><\/tr><\/thead><tbody><tr><td>Anonymous users route<\/td><td>Blocked (404)<\/td><td>Blocked (401)<\/td><td>Blocked (401)<\/td><\/tr><tr><td>Block editor author dropdown<\/td><td>Broken<\/td><td>Works<\/td><td>Works<\/td><\/tr><tr><td>WooCommerce admin REST calls<\/td><td>Works<\/td><td>Works<\/td><td>Works<\/td><\/tr><tr><td>wp-abilities\/v1 discovery (7.0)<\/td><td>Works<\/td><td>Broken<\/td><td>Works<\/td><\/tr><tr><td>Headless front end author data<\/td><td>Broken<\/td><td>Broken<\/td><td>Broken unless exempted<\/td><\/tr><tr><td>Other three enumeration doors<\/td><td>Still open<\/td><td>Still open<\/td><td>Still open<\/td><\/tr><tr><td>Site Health REST loopback<\/td><td>Works<\/td><td>Fails<\/td><td>Works<\/td><\/tr><\/tbody><\/table><figcaption class=\"wp-element-caption\">The REST Restriction Blast-Radius Table: what each of the three published methods costs across seven live surfaces.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Two rows deserve emphasis, and both explain why teams that stop REST API user enumeration once still report breakage weeks later. Unsetting the routes removes them for authenticated administrators too, which is why sites that apply it report a broken author dropdown days later without connecting the two events. A site-wide anonymous block, applied through the <a href=\"https:\/\/developer.wordpress.org\/reference\/hooks\/rest_authentication_errors\/\" target=\"_blank\" rel=\"noopener\">rest_authentication_errors filter<\/a>, is heavier still. Stores feel that second one first, since <a href=\"https:\/\/www.ahosting.net\/woocommerce-hosting.html\">WooCommerce hosting environments<\/a> run several integrations that assume REST answers predictably.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The final row is the point of the whole exercise. Every method closes exactly one of the four doors, so no row in this table represents a finished job on its own.<\/p>\n\n\n\n<h2 id=\"wordpress-7-abilities\" class=\"wp-block-heading\">WordPress 7.0 Changed the Cost of Blocking REST Traffic Site-Wide<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The blunt fix got more expensive in 2026, and the reason is a namespace most site owners have never opened.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The Abilities API arrived in WordPress 6.9 as a registry that lets plugins, themes, and core declare named capabilities with input and output schemas and permission rules. WordPress 7.0, released in May 2026, shipped its <a href=\"https:\/\/make.wordpress.org\/core\/2026\/03\/24\/client-side-abilities-api-in-wordpress-7-0\/\" target=\"_blank\" rel=\"noopener\">JavaScript client counterpart<\/a> along with REST endpoints under the wp-abilities\/v1 namespace, and core itself registers a small initial set covering site, environment, and current-user information. WordPress 7.1 extends how those abilities are discovered and filtered through the same REST collection.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Those routes run their own permission callbacks, so they are not an anonymous disclosure problem. The consequence is the opposite one. A filter that returns an error for every unauthenticated REST request now takes down agent and AI-client discovery as a side effect, on a site whose owner was only trying to hide four usernames. Sites already reviewing what the 7.0 release turned on will find the same reasoning in our guide to <a href=\"https:\/\/www.ahosting.net\/blog\/disable-wordpress-ai-features\/\">disabling the WordPress AI features introduced in 7.0<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Scoping the fix to the users routes avoids the trade entirely, which is why the capability gate is the recommendation here rather than a compromise.<\/p>\n\n\n\n<h2 id=\"exposure-checker\" class=\"wp-block-heading\">Check Your Own Exposure Before You Stop REST API User Enumeration<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Run the four checks below in a private browsing window, logged out, before and after you deploy the file. The checker records which doors are open and interprets the combination.<\/p>\n\n\n\n<style>.ahenum-tool{background:#0f172a;border-radius:10px;padding:26px;margin:28px 0;color:#e2e8f0;}\n.ahenum-tool h3{color:#fff;margin:0 0 8px;font-size:1.35rem;}\n.ahenum-tool p.ahenum-lede{color:#cbd5e1;margin:0 0 18px;font-size:.95rem;}\n.ahenum-row{border-top:1px solid #1e293b;padding:12px 0;}\n.ahenum-q{display:block;color:#e2e8f0;font-size:.95rem;margin-bottom:8px;}\n.ahenum-b{background:#1e293b;color:#e2e8f0;border:1px solid #334155;border-radius:6px;padding:7px 14px;margin-right:8px;font-size:.9rem;cursor:pointer;}\n.ahenum-on{background:#2563eb;border-color:#2563eb;color:#fff;}\n.ahenum-out{background:#1e293b;border-left:4px solid #2563eb;border-radius:6px;padding:16px;margin-top:18px;color:#e2e8f0;font-size:.95rem;}\n.ahenum-out strong{color:#fff;}\na.ahenum-btn.wp-element-button{display:inline-block;margin-top:16px;background:#2563eb!important;color:#fff!important;text-decoration:none!important;padding:11px 20px;border-radius:6px;font-size:.95rem;}<\/style>\n<div class=\"ahenum-tool\">\n<h3>Username Exposure Checker<\/h3>\n<p class=\"ahenum-lede\">Answer for the site you are auditing. Each answer describes what an anonymous visitor gets today, not what you intend to configure.<\/p>\n<div class=\"ahenum-row\"><span class=\"ahenum-q\">1. Does \/wp-json\/wp\/v2\/users return an author array when you are logged out?<\/span><button type=\"button\" class=\"ahenum-b\" data-ahenum=\"door1\" data-state=\"open\">Returns authors<\/button><button type=\"button\" class=\"ahenum-b\" data-ahenum=\"door1\" data-state=\"closed\">401 or 404<\/button><\/div>\n<div class=\"ahenum-row\"><span class=\"ahenum-q\">2. Does \/?author=1 redirect to an author archive URL containing a slug?<\/span><button type=\"button\" class=\"ahenum-b\" data-ahenum=\"door2\" data-state=\"open\">Redirects<\/button><button type=\"button\" class=\"ahenum-b\" data-ahenum=\"door2\" data-state=\"closed\">Home or 404<\/button><\/div>\n<div class=\"ahenum-row\"><span class=\"ahenum-q\">3. Does \/wp-sitemap-users-1.xml list author archive URLs?<\/span><button type=\"button\" class=\"ahenum-b\" data-ahenum=\"door3\" data-state=\"open\">Lists authors<\/button><button type=\"button\" class=\"ahenum-b\" data-ahenum=\"door3\" data-state=\"closed\">404<\/button><\/div>\n<div class=\"ahenum-row\"><span class=\"ahenum-q\">4. Does the oEmbed response for any post carry author_name and author_url?<\/span><button type=\"button\" class=\"ahenum-b\" data-ahenum=\"door4\" data-state=\"open\">Carries both<\/button><button type=\"button\" class=\"ahenum-b\" data-ahenum=\"door4\" data-state=\"closed\">Stripped<\/button><\/div>\n<div class=\"ahenum-out\">Answer all four questions to see your exposure profile.<\/div>\n<a class=\"ahenum-btn wp-element-button\" href=\"https:\/\/www.ahosting.net\/wordpress-hosting.html\">See what ships hardened on AHosting WordPress Hosting<\/a>\n<\/div>\n<script>(function(){\n  document.addEventListener('DOMContentLoaded', function(){\n    var W = document.querySelector('.ahenum-tool');\n    if (!W) { return; }\n    var OUT = W.querySelector('.ahenum-out');\n    if (!OUT) { return; }\n    var state = {door1:'', door2:'', door3:'', door4:''};\n    var keys = ['door1','door2','door3','door4'];\n    function render(){\n      var answered = 0;\n      var open = 0;\n      for (var i = 0; i < keys.length; i++) {\n        var v = state[keys[i]];\n        if (v !== '') { answered = answered + 1; }\n        if (v === 'open') { open = open + 1; }\n      }\n      if (answered < 4) {\n        OUT.innerHTML = 'Answered ' + answered + ' of 4. Complete the checklist to see your exposure profile.';\n        return;\n      }\n      if (open === 0) {\n        OUT.innerHTML = '<strong>All four doors closed.<\/strong> Re-run this check after any theme switch, plugin change, or migration, because three of these fixes live in code that a restore can overwrite.';\n        return;\n      }\n      if (open === 4) {\n        OUT.innerHTML = '<strong>Default configuration: all four doors open.<\/strong> This is stock WordPress behavior, not a breach. Apply the mu-plugin in the section above, then re-test each route while logged out.';\n        return;\n      }\n      var label = 'door';\n      if (open > 1) { label = 'doors'; }\n      OUT.innerHTML = '<strong>Partial: ' + open + ' of 4 ' + label + ' still open.<\/strong> A partially closed surface still yields a complete author list, because the vectors return the same slugs by different routes. Close the remaining ' + label + ' before treating this as fixed.';\n    }\n    W.addEventListener('click', function(e){\n      var t = e.target;\n      if (!t) { return; }\n      var key = t.getAttribute('data-ahenum');\n      if (!key) { return; }\n      var val = t.getAttribute('data-state');\n      if (!val) { return; }\n      state[key] = val;\n      var group = t.parentNode;\n      if (group) {\n        var bs = group.querySelectorAll('button');\n        for (var j = 0; j < bs.length; j++) { bs[j].className = 'ahenum-b'; }\n      }\n      t.className = 'ahenum-b ahenum-on';\n      render();\n    });\n  });\n})();<\/script>\n\n\n\n<p class=\"wp-block-paragraph\">Test while logged out without exception. An administrator session passes the capability check, so a logged-in test returns author data on a correctly hardened site and reads as a failure.<\/p>\n\n\n\n<h2 id=\"hosting-context\" class=\"wp-block-heading\">Where Hosting Sits: Server-Level Context on AHosting WordPress Hosting<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Enumeration is an application-layer disclosure, so no hosting plan closes it for you. The server layer still governs what the probing costs while it happens.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">These routes are never served from cache. A cached page consumes no PHP worker at all, but a REST request and an author redirect both reach PHP, and each concurrent request occupies one entry process. AHosting allocates entry processes by tier, at 15 on Bronze, 25 on Silver, and 40 on Gold. A scripted sweep across a numeric ID range is therefore a small, sustained draw on the same pool your visitors use. When that pool saturates, CloudLinux queues requests rather than rejecting them instantly, and the LiteSpeed connection timeout of 120 seconds is the window before a queued request is answered with a 503. Our guide to the <a href=\"https:\/\/www.ahosting.net\/blog\/508-resource-limit-reached-wordpress\/\">entry-process ceiling behind resource-limit errors<\/a> covers that mechanism in full.<\/p>\n\n\n\n<h3 id=\"cost-of-leaving-it-open\" class=\"wp-block-heading\">What It Costs to Leave REST API User Enumeration Open<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Reconnaissance is also the first half of a longer sequence. A collected username list feeds the login and endpoint floods described in our guide to <a href=\"https:\/\/www.ahosting.net\/blog\/stop-xml-rpc-bot-flood\/\">stopping an XML-RPC bot flood<\/a>, and the server-side controls in our overview of <a href=\"https:\/\/www.ahosting.net\/blog\/wordpress-hosting-security-2026-server-level-protection\/\">WordPress hosting security below the plugin layer<\/a> are what absorb the second half. Sites where sustained bot traffic competes with real visitors for the same worker pool are the usual candidates for <a href=\"https:\/\/www.ahosting.net\/vps-hosting.html\">moving to a VPS with a worker pool you size yourself<\/a>, or for <a href=\"https:\/\/www.ahosting.net\/dedicated-server.html\">dedicated hardware once shared infrastructure is genuinely outgrown<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">One deployment note specific to shared accounts. Upload the file rather than pasting into a theme editor, and if a syntax error takes the site down, the recovery path is in our guide to the <a href=\"https:\/\/www.ahosting.net\/blog\/wordpress-white-screen-of-death\/\">WordPress white screen of death<\/a>. Every AHosting WordPress plan also ships a free dedicated IP and CloudLinux CageFS isolation, which govern reputation and containment rather than disclosure.<\/p>\n\n\n\n<h2 id=\"checklist\" class=\"wp-block-heading\">A Checklist to Stop REST API User Enumeration and Keep It Closed<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Work through this once at deployment, then re-run the verification half after any migration, restore, or theme change. The steps that stop REST API user enumeration are code; the steps that keep it stopped are habit.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Create wp-content\/mu-plugins and upload a single hardening file rather than editing a theme.<\/li>\n\n\n\n<li>Gate the two users routes by capability instead of unsetting them.<\/li>\n\n\n\n<li>Redirect the numeric author query, unless author archives are deliberately public.<\/li>\n\n\n\n<li>Remove the users provider from the automatic sitemap and confirm the index no longer lists it.<\/li>\n\n\n\n<li>Strip author_name and author_url from the oEmbed response.<\/li>\n\n\n\n<li>Verify all four routes from a logged-out private window, never from an admin session.<\/li>\n\n\n\n<li>Confirm the block editor author dropdown still populates after deployment.<\/li>\n\n\n\n<li>Change the author slug on any account where it still equals the login name.<\/li>\n\n\n\n<li>Re-test after every restore, because three of these fixes live in a file a rollback can remove.<\/li>\n\n\n\n<li>Record the scan finding as a reviewed configuration decision rather than an open vulnerability.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Above all, treat the slug change as the step that outlasts the rest. Fixing the routes hides the mapping, whereas breaking the link between slug and login name removes the value of the mapping even if a future change reopens a door.<\/p>\n\n\n\n<h2 id=\"faq-stop-rest-api-user-enumeration\" class=\"wp-block-heading\">Frequently Asked Questions: Stop REST API User Enumeration<\/h2>\n\n\n\n<h3 id=\"faq-turn-off-rest-api-gutenberg\" class=\"wp-block-heading\">How do I turn off the REST API in WordPress without breaking Gutenberg in 2026?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Specifically, do not turn the whole REST API off. Gate only the two users routes behind a capability check with the rest_endpoints filter, which leaves every other route reachable. Gutenberg, WooCommerce admin screens, and the WordPress 7.0 ability endpoints all keep working because their requests carry an authenticated session. A site-wide authentication block is the version of this fix that breaks the editor, and the blast-radius table earlier in this guide shows exactly which six surfaces it takes down.<\/p>\n\n\n\n<h3 id=\"faq-rest-endpoints-vs-authentication-errors\" class=\"wp-block-heading\">rest_endpoints vs rest_authentication_errors: which filter should I use to stop REST API user enumeration?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Therefore the answer depends on scope. The rest_endpoints filter edits the route table itself, so it can target the users collection and single-user routes and leave everything else alone. The rest_authentication_errors filter sits in front of every route at once, which makes it a blunt instrument for this job. Use rest_endpoints with a permission callback for enumeration, and reserve rest_authentication_errors for genuinely private installations where no route should answer an anonymous request.<\/p>\n\n\n\n<h3 id=\"faq-wp-abilities-namespace-2026\" class=\"wp-block-heading\">Does WordPress 7.0 expose more user data through the wp-abilities\/v1 namespace in 2026?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Notably, it adds a second REST namespace rather than more public user data. WordPress 6.9 introduced the Abilities API and WordPress 7.0 shipped its JavaScript client, registering a small core set covering site, environment, and current-user information under wp-abilities\/v1. Those abilities run permission callbacks of their own, so they are not an anonymous disclosure route. The practical consequence is different: a blanket authentication block now silently disables agent and AI-client discovery as well.<\/p>\n\n\n\n<h3 id=\"faq-reseller-thirty-client-sites\" class=\"wp-block-heading\">Should I stop REST API user enumeration on an AHosting reseller account hosting 30 client sites?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Ultimately yes, and the reseller case is the strongest one. Every client site under a reseller account publishes its own author list, so a single scripted pass across 30 domains returns 30 username sets from one afternoon of work. Deploy the same mu-plugin file to each account rather than editing 30 themes, because a theme switch on any one site silently reopens the door. The exposure matrix in this guide lists the four vectors each deployment has to close.<\/p>\n\n\n\n<h3 id=\"faq-scanner-reports-cve-2017-5487\" class=\"wp-block-heading\">Why does my security scanner still report CVE-2017-5487 on a fully patched WordPress 7.0 site?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">In fact, that finding is almost always a misattribution. CVE-2017-5487 was fixed in WordPress 4.7.1 in January 2017, which narrowed the users endpoint to authors of post types that opt into REST. What your scanner detects today is the remaining intended behavior, not the unpatched flaw, and several scanner templates simply map any reachable users route to the old identifier. Treat it as a configuration finding to decide on, never as evidence of an unpatched core.<\/p>\n\n\n\n<h3 id=\"faq-author-archive-vs-rest-restriction\" class=\"wp-block-heading\">Author archive redirect vs REST endpoint restriction: which closes more username exposure?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">By contrast with the common assumption, neither one closes the exposure alone. The REST restriction shuts the route most scanners probe first, while the author redirect shuts the oldest vector, the numeric author query that resolves to a slug in the URL. Two further doors stay open behind both of them, namely the core users sitemap and the oEmbed response. Closing any single door moves the attacker to the next one rather than stopping the collection.<\/p>\n\n\n\n<h3 id=\"faq-mu-plugin-ahosting-2026\" class=\"wp-block-heading\">Can an mu-plugin stop REST API user enumeration on AHosting WordPress hosting in 2026?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Fortunately yes, and an mu-plugin is the right delivery method on any cPanel account. Files placed in wp-content\/mu-plugins load automatically, cannot be deactivated from the dashboard, and survive both theme changes and core updates, which is where functions.php edits usually fail. Create the directory through the cPanel File Manager if it does not exist yet, then upload a single PHP file containing all four fixes. No support ticket and no server-level change is required.<\/p>\n\n\n\n<h3 id=\"faq-headless-users-endpoint\" class=\"wp-block-heading\">What happens if I stop REST API user enumeration on a headless WordPress site using the users endpoint?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Consequently, a headless front end that renders author bylines from the users route will start receiving empty responses. Handle it by exempting a specific application password or by embedding author data in the posts response with the _embed parameter instead of a separate users call. Test the front end against a staging copy before deploying, because the failure is a missing byline rather than a visible error, and that is easy to ship without noticing.<\/p>\n\n\n\n<h3 id=\"faq-username-exposure-matrix\" class=\"wp-block-heading\">What is the AHosting Username Exposure Matrix and which four vectors does it cover?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Similarly to a pre-flight checklist, it is a four-row reference that maps every core route that publishes an author slug against the fix that closes it. The four vectors are the REST users routes, the numeric author query redirect, the core users sitemap added in WordPress 5.5, and the oEmbed embed endpoint. Each row also records what remains reachable if you close only the REST route, which is the mistake most published guides encourage.<\/p>\n\n\n\n<h3 id=\"faq-dedicated-ip-enumeration-attempts\" class=\"wp-block-heading\">Does a dedicated IP address help stop REST API user enumeration attempts before they reach WordPress?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Interestingly, a dedicated IP changes reputation rather than reachability. Enumeration probes target your domain, so they arrive whichever address answers, and the request still reaches PHP because these routes are never served from cache. What a dedicated IP does change is that your address carries no other tenant's history, so firewall reputation decisions about your traffic reflect only your own site. Isolation and the application-layer fix solve different halves of the problem.<\/p>\n\n\n\n<script>\n(function(){\n  document.addEventListener('DOMContentLoaded', function(){\n    var allH3s = document.querySelectorAll('h3.wp-block-heading');\n    var inFaq = false;\n    for (var i = 0; i < allH3s.length; i++) {\n      var h3 = allH3s[i];\n      var prev = h3.previousElementSibling;\n      if (prev) {\n        if (prev.tagName === 'H2') {\n          var prevId = prev.getAttribute('id');\n          if (prevId) {\n            if (prevId.indexOf('faq-') === 0) {\n              inFaq = true;\n            } else {\n              inFaq = false;\n            }\n          }\n        }\n      }\n      if (inFaq) {\n        initToggle(h3);\n      }\n    }\n    function initToggle(h3) {\n      var answer = h3.nextElementSibling;\n      if (!answer) { return; }\n      if (answer.tagName !== 'P') { return; }\n      var chev = document.createElement('span');\n      chev.className = 'ahfaq-chev ahfaq-chev-closed';\n      chev.setAttribute('aria-hidden', 'true');\n      h3.appendChild(chev);\n      h3.setAttribute('tabindex', '0');\n      h3.setAttribute('aria-expanded', 'false');\n      answer.classList.add('ahfaq-collapsed');\n      h3.addEventListener('click', function(){ doToggle(h3, answer, chev); });\n      h3.addEventListener('keydown', function(e){\n        if (e.key === 'Enter') { e.preventDefault(); doToggle(h3, answer, chev); }\n        if (e.key === ' ') { e.preventDefault(); doToggle(h3, answer, chev); }\n      });\n    }\n    function doToggle(h3, answer, chev) {\n      var isOpen = h3.getAttribute('aria-expanded') === 'true';\n      if (isOpen) {\n        answer.classList.remove('ahfaq-open');\n        answer.classList.add('ahfaq-collapsed');\n        h3.setAttribute('aria-expanded', 'false');\n        chev.classList.add('ahfaq-chev-closed');\n        chev.classList.remove('ahfaq-chev-open');\n      } else {\n        answer.classList.remove('ahfaq-collapsed');\n        answer.classList.add('ahfaq-open');\n        h3.setAttribute('aria-expanded', 'true');\n        chev.classList.remove('ahfaq-chev-closed');\n        chev.classList.add('ahfaq-chev-open');\n      }\n    }\n  });\n})();\n<\/script>\n\n","protected":false},"excerpt":{"rendered":"<p>TL;DR To stop REST API user enumeration, gate the users routes by capability in an mu-plugin, then close the author redirect, the users sitemap, and the oEmbed author fields. Verify all four while logged out. You can stop REST API user enumeration on a WordPress site in about ten minutes. The complication is that most [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":1155,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"footnotes":""},"categories":[26],"tags":[237,235,234,236,175,138],"class_list":["post-1154","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-security","tag-hardening","tag-mu-plugin","tag-rest-api","tag-user-enumeration","tag-wordpress-7-0","tag-wordpress-security"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.0.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"Stop REST API user enumeration in WordPress without breaking the block editor. Four doors leak author slugs. One mu-plugin closes all of them.\" \/>\n\t<meta name=\"robots\" content=\"max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n\t<meta name=\"author\" content=\"Matt Chrust\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/www.ahosting.net\/blog\/stop-rest-api-user-enumeration\/\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.0.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"Blog Home | AHosting Blog\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"Stop REST API User Enumeration - 2026 Fix | AHosting\" \/>\n\t\t<meta property=\"og:description\" content=\"Stop REST API user enumeration in WordPress without breaking the block editor. Four doors leak author slugs. One mu-plugin closes all of them.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/www.ahosting.net\/blog\/stop-rest-api-user-enumeration\/\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/www.ahosting.net\/blog\/wp-content\/uploads\/2026\/08\/stop-rest-api-user-enumeration-ahosting.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/www.ahosting.net\/blog\/wp-content\/uploads\/2026\/08\/stop-rest-api-user-enumeration-ahosting.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t\t<meta property=\"og:image:height\" content=\"675\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2026-08-20T18:34:21+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2026-08-21T16:44:30+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n\t\t<meta name=\"twitter:site\" content=\"@ahostingdotnet\" \/>\n\t\t<meta name=\"twitter:title\" content=\"Stop REST API User Enumeration - 2026 Fix | AHosting\" \/>\n\t\t<meta name=\"twitter:description\" content=\"Stop REST API user enumeration in WordPress without breaking the block editor. Four doors leak author slugs. One mu-plugin closes all of them.\" \/>\n\t\t<meta name=\"twitter:creator\" content=\"@ahostingdotnet\" \/>\n\t\t<meta name=\"twitter:image\" content=\"https:\/\/www.ahosting.net\/blog\/wp-content\/uploads\/2026\/08\/stop-rest-api-user-enumeration-ahosting.jpg\" \/>\n\t\t<script type=\"application\/ld+json\" class=\"aioseo-schema\">\n\t\t\t{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"BlogPosting\",\"@id\":\"https:\\\/\\\/www.ahosting.net\\\/blog\\\/stop-rest-api-user-enumeration\\\/#article\",\"name\":\"Stop REST API User Enumeration - 2026 Fix | AHosting\",\"headline\":\"Stop REST API User Enumeration in WordPress (2026)\",\"author\":{\"@type\":\"Person\",\"name\":\"Matt Chrust\",\"url\":\"https:\\\/\\\/www.ahosting.net\\\/blog\\\/author\\\/matt-chrust\\\/\"},\"publisher\":{\"@id\":\"https:\\\/\\\/www.ahosting.net\\\/#organization\"},\"image\":{\"@type\":\"ImageObject\",\"url\":\"https:\\\/\\\/www.ahosting.net\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/08\\\/stop-rest-api-user-enumeration-ahosting.jpg\",\"width\":1200,\"height\":675,\"caption\":\"The four core routes that publish WordPress author slugs, and what each returns to an anonymous request. By Matt Chrust, Director of Business Development, AHosting.\"},\"datePublished\":\"2026-08-20T18:34:21+00:00\",\"dateModified\":\"2026-08-21T16:44:30+00:00\",\"inLanguage\":\"en-US\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.ahosting.net\\\/blog\\\/stop-rest-api-user-enumeration\\\/#webpage\"},\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.ahosting.net\\\/blog\\\/stop-rest-api-user-enumeration\\\/#webpage\"},\"articleSection\":\"Security, hardening, mu-plugin, REST API, user enumeration, WordPress 7.0, wordpress security\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.ahosting.net\\\/blog\\\/stop-rest-api-user-enumeration\\\/#breadcrumblist\",\"itemListElement\":[{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.ahosting.net\\\/blog#listItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.ahosting.net\\\/blog\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.ahosting.net\\\/blog\\\/category\\\/security\\\/#listItem\",\"name\":\"Security\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.ahosting.net\\\/blog\\\/category\\\/security\\\/#listItem\",\"position\":2,\"name\":\"Security\",\"item\":\"https:\\\/\\\/www.ahosting.net\\\/blog\\\/category\\\/security\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.ahosting.net\\\/blog\\\/stop-rest-api-user-enumeration\\\/#listItem\",\"name\":\"Stop REST API User Enumeration in WordPress (2026)\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.ahosting.net\\\/blog#listItem\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.ahosting.net\\\/blog\\\/stop-rest-api-user-enumeration\\\/#listItem\",\"position\":3,\"name\":\"Stop REST API User Enumeration in WordPress (2026)\",\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.ahosting.net\\\/blog\\\/category\\\/security\\\/#listItem\",\"name\":\"Security\"},\"item\":\"https:\\\/\\\/www.ahosting.net\\\/blog\\\/stop-rest-api-user-enumeration\\\/\"}]},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.ahosting.net\\\/#organization\",\"name\":\"AHosting\",\"description\":\"AHosting Blog\",\"url\":\"https:\\\/\\\/www.ahosting.net\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https:\\\/\\\/www.ahosting.net\\\/assets\\\/img\\\/ahosting-logo.svg\",\"@id\":\"https:\\\/\\\/www.ahosting.net\\\/blog\\\/stop-rest-api-user-enumeration\\\/#organizationLogo\"},\"image\":{\"@id\":\"https:\\\/\\\/www.ahosting.net\\\/blog\\\/stop-rest-api-user-enumeration\\\/#organizationLogo\"},\"sameAs\":[\"https:\\\/\\\/x.com\\\/ahostingdotnet\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.ahosting.net\\\/blog\\\/author\\\/matt-chrust\\\/#author\",\"url\":\"https:\\\/\\\/www.ahosting.net\\\/blog\\\/author\\\/matt-chrust\\\/\",\"name\":\"Matt Chrust\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\\\/\\\/www.ahosting.net\\\/blog\\\/stop-rest-api-user-enumeration\\\/#authorImage\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/795895edac1c44589f6c7f5e6bb79df405fbbaac15817bdd387ec57da61731ec?s=96&d=mm&r=g\",\"width\":96,\"height\":96,\"caption\":\"Matt Chrust\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.ahosting.net\\\/blog\\\/stop-rest-api-user-enumeration\\\/#webpage\",\"url\":\"https:\\\/\\\/www.ahosting.net\\\/blog\\\/stop-rest-api-user-enumeration\\\/\",\"name\":\"Stop REST API User Enumeration - 2026 Fix | AHosting\",\"description\":\"Stop REST API user enumeration in WordPress without breaking the block editor. Four doors leak author slugs. One mu-plugin closes all of them.\",\"inLanguage\":\"en-US\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.ahosting.net\\\/blog\\\/#website\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.ahosting.net\\\/blog\\\/stop-rest-api-user-enumeration\\\/#breadcrumblist\"},\"author\":{\"@id\":\"https:\\\/\\\/www.ahosting.net\\\/blog\\\/author\\\/matt-chrust\\\/#author\"},\"creator\":{\"@id\":\"https:\\\/\\\/www.ahosting.net\\\/blog\\\/author\\\/matt-chrust\\\/#author\"},\"image\":{\"@type\":\"ImageObject\",\"url\":\"https:\\\/\\\/www.ahosting.net\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/08\\\/stop-rest-api-user-enumeration-ahosting.jpg\",\"@id\":\"https:\\\/\\\/www.ahosting.net\\\/blog\\\/stop-rest-api-user-enumeration\\\/#mainImage\",\"width\":1200,\"height\":675,\"caption\":\"The four core routes that publish WordPress author slugs, and what each returns to an anonymous request. By Matt Chrust, Director of Business Development, AHosting.\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.ahosting.net\\\/blog\\\/stop-rest-api-user-enumeration\\\/#mainImage\"},\"datePublished\":\"2026-08-20T18:34:21+00:00\",\"dateModified\":\"2026-08-21T16:44:30+00:00\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.ahosting.net\\\/#website\",\"url\":\"https:\\\/\\\/www.ahosting.net\\\/\",\"name\":\"AHosting\",\"description\":\"AHosting Blog\",\"inLanguage\":\"en-US\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.ahosting.net\\\/#organization\"}}]}\n\t\t<\/script>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"Stop REST API User Enumeration - 2026 Fix | AHosting","description":"Stop REST API user enumeration in WordPress without breaking the block editor. Four doors leak author slugs. One mu-plugin closes all of them.","canonical_url":"https:\/\/www.ahosting.net\/blog\/stop-rest-api-user-enumeration\/","robots":"max-snippet:-1, max-image-preview:large, max-video-preview:-1","keywords":"","webmasterTools":{"miscellaneous":""},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"BlogPosting","@id":"https:\/\/www.ahosting.net\/blog\/stop-rest-api-user-enumeration\/#article","name":"Stop REST API User Enumeration - 2026 Fix | AHosting","headline":"Stop REST API User Enumeration in WordPress (2026)","author":{"@type":"Person","name":"Matt Chrust","url":"https:\/\/www.ahosting.net\/blog\/author\/matt-chrust\/"},"publisher":{"@id":"https:\/\/www.ahosting.net\/#organization"},"image":{"@type":"ImageObject","url":"https:\/\/www.ahosting.net\/blog\/wp-content\/uploads\/2026\/08\/stop-rest-api-user-enumeration-ahosting.jpg","width":1200,"height":675,"caption":"The four core routes that publish WordPress author slugs, and what each returns to an anonymous request. By Matt Chrust, Director of Business Development, AHosting."},"datePublished":"2026-08-20T18:34:21+00:00","dateModified":"2026-08-21T16:44:30+00:00","inLanguage":"en-US","mainEntityOfPage":{"@id":"https:\/\/www.ahosting.net\/blog\/stop-rest-api-user-enumeration\/#webpage"},"isPartOf":{"@id":"https:\/\/www.ahosting.net\/blog\/stop-rest-api-user-enumeration\/#webpage"},"articleSection":"Security, hardening, mu-plugin, REST API, user enumeration, WordPress 7.0, wordpress security"},{"@type":"BreadcrumbList","@id":"https:\/\/www.ahosting.net\/blog\/stop-rest-api-user-enumeration\/#breadcrumblist","itemListElement":[{"@type":"ListItem","@id":"https:\/\/www.ahosting.net\/blog#listItem","position":1,"name":"Home","item":"https:\/\/www.ahosting.net\/blog","nextItem":{"@type":"ListItem","@id":"https:\/\/www.ahosting.net\/blog\/category\/security\/#listItem","name":"Security"}},{"@type":"ListItem","@id":"https:\/\/www.ahosting.net\/blog\/category\/security\/#listItem","position":2,"name":"Security","item":"https:\/\/www.ahosting.net\/blog\/category\/security\/","nextItem":{"@type":"ListItem","@id":"https:\/\/www.ahosting.net\/blog\/stop-rest-api-user-enumeration\/#listItem","name":"Stop REST API User Enumeration in WordPress (2026)"},"previousItem":{"@type":"ListItem","@id":"https:\/\/www.ahosting.net\/blog#listItem","name":"Home"}},{"@type":"ListItem","@id":"https:\/\/www.ahosting.net\/blog\/stop-rest-api-user-enumeration\/#listItem","position":3,"name":"Stop REST API User Enumeration in WordPress (2026)","previousItem":{"@type":"ListItem","@id":"https:\/\/www.ahosting.net\/blog\/category\/security\/#listItem","name":"Security"},"item":"https:\/\/www.ahosting.net\/blog\/stop-rest-api-user-enumeration\/"}]},{"@type":"Organization","@id":"https:\/\/www.ahosting.net\/#organization","name":"AHosting","description":"AHosting Blog","url":"https:\/\/www.ahosting.net\/","logo":{"@type":"ImageObject","url":"https:\/\/www.ahosting.net\/assets\/img\/ahosting-logo.svg","@id":"https:\/\/www.ahosting.net\/blog\/stop-rest-api-user-enumeration\/#organizationLogo"},"image":{"@id":"https:\/\/www.ahosting.net\/blog\/stop-rest-api-user-enumeration\/#organizationLogo"},"sameAs":["https:\/\/x.com\/ahostingdotnet"]},{"@type":"Person","@id":"https:\/\/www.ahosting.net\/blog\/author\/matt-chrust\/#author","url":"https:\/\/www.ahosting.net\/blog\/author\/matt-chrust\/","name":"Matt Chrust","image":{"@type":"ImageObject","@id":"https:\/\/www.ahosting.net\/blog\/stop-rest-api-user-enumeration\/#authorImage","url":"https:\/\/secure.gravatar.com\/avatar\/795895edac1c44589f6c7f5e6bb79df405fbbaac15817bdd387ec57da61731ec?s=96&d=mm&r=g","width":96,"height":96,"caption":"Matt Chrust"}},{"@type":"WebPage","@id":"https:\/\/www.ahosting.net\/blog\/stop-rest-api-user-enumeration\/#webpage","url":"https:\/\/www.ahosting.net\/blog\/stop-rest-api-user-enumeration\/","name":"Stop REST API User Enumeration - 2026 Fix | AHosting","description":"Stop REST API user enumeration in WordPress without breaking the block editor. Four doors leak author slugs. One mu-plugin closes all of them.","inLanguage":"en-US","isPartOf":{"@id":"https:\/\/www.ahosting.net\/blog\/#website"},"breadcrumb":{"@id":"https:\/\/www.ahosting.net\/blog\/stop-rest-api-user-enumeration\/#breadcrumblist"},"author":{"@id":"https:\/\/www.ahosting.net\/blog\/author\/matt-chrust\/#author"},"creator":{"@id":"https:\/\/www.ahosting.net\/blog\/author\/matt-chrust\/#author"},"image":{"@type":"ImageObject","url":"https:\/\/www.ahosting.net\/blog\/wp-content\/uploads\/2026\/08\/stop-rest-api-user-enumeration-ahosting.jpg","@id":"https:\/\/www.ahosting.net\/blog\/stop-rest-api-user-enumeration\/#mainImage","width":1200,"height":675,"caption":"The four core routes that publish WordPress author slugs, and what each returns to an anonymous request. By Matt Chrust, Director of Business Development, AHosting."},"primaryImageOfPage":{"@id":"https:\/\/www.ahosting.net\/blog\/stop-rest-api-user-enumeration\/#mainImage"},"datePublished":"2026-08-20T18:34:21+00:00","dateModified":"2026-08-21T16:44:30+00:00"},{"@type":"WebSite","@id":"https:\/\/www.ahosting.net\/#website","url":"https:\/\/www.ahosting.net\/","name":"AHosting","description":"AHosting Blog","inLanguage":"en-US","publisher":{"@id":"https:\/\/www.ahosting.net\/#organization"}}]},"og:locale":"en_US","og:site_name":"Blog Home | AHosting Blog","og:type":"article","og:title":"Stop REST API User Enumeration - 2026 Fix | AHosting","og:description":"Stop REST API user enumeration in WordPress without breaking the block editor. Four doors leak author slugs. One mu-plugin closes all of them.","og:url":"https:\/\/www.ahosting.net\/blog\/stop-rest-api-user-enumeration\/","og:image":"https:\/\/www.ahosting.net\/blog\/wp-content\/uploads\/2026\/08\/stop-rest-api-user-enumeration-ahosting.jpg","og:image:secure_url":"https:\/\/www.ahosting.net\/blog\/wp-content\/uploads\/2026\/08\/stop-rest-api-user-enumeration-ahosting.jpg","og:image:width":1200,"og:image:height":675,"article:published_time":"2026-08-20T18:34:21+00:00","article:modified_time":"2026-08-21T16:44:30+00:00","twitter:card":"summary_large_image","twitter:site":"@ahostingdotnet","twitter:title":"Stop REST API User Enumeration - 2026 Fix | AHosting","twitter:description":"Stop REST API user enumeration in WordPress without breaking the block editor. Four doors leak author slugs. One mu-plugin closes all of them.","twitter:creator":"@ahostingdotnet","twitter:image":"https:\/\/www.ahosting.net\/blog\/wp-content\/uploads\/2026\/08\/stop-rest-api-user-enumeration-ahosting.jpg"},"aioseo_meta_data":{"post_id":"1154","title":"Stop REST API User Enumeration - 2026 Fix | AHosting","description":"Stop REST API user enumeration in WordPress without breaking the block editor. Four doors leak author slugs. One mu-plugin closes all of them.","keywords":null,"keyphrases":{"focus":{"keyphrase":"stop REST API user enumeration","score":0,"analysis":[]},"additional":[]},"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":"","og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"Article","isEnabled":true},"graphs":[]},"schema_type":"default","schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":"-1","robots_max_videopreview":"-1","robots_max_imagepreview":"large","priority":null,"frequency":"default","local_seo":null,"breadcrumb_settings":null,"limit_modified_date":false,"ai":{"faqs":[],"keyPoints":[],"schemas":[],"titles":[],"descriptions":[],"socialPosts":{"email":{"subject":"","preview":"","content":""},"linkedin":[],"twitter":[],"facebook":[],"instagram":[]}},"created":"2026-08-20 18:26:35","updated":"2026-08-21 16:46:37","seo_analyzer_scan_date":null,"focus_keyword":"stop REST API user enumeration","additional_keywords":null,"truseo_locale":null},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.ahosting.net\/blog\" title=\"Home\">Home<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.ahosting.net\/blog\/category\/security\/\" title=\"Security\">Security<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\tStop REST API User Enumeration in WordPress (2026)\n\t\t<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/www.ahosting.net\/blog"},{"label":"Security","link":"https:\/\/www.ahosting.net\/blog\/category\/security\/"},{"label":"Stop REST API User Enumeration in WordPress (2026)","link":"https:\/\/www.ahosting.net\/blog\/stop-rest-api-user-enumeration\/"}],"_links":{"self":[{"href":"https:\/\/www.ahosting.net\/blog\/wp-json\/wp\/v2\/posts\/1154","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.ahosting.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.ahosting.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.ahosting.net\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ahosting.net\/blog\/wp-json\/wp\/v2\/comments?post=1154"}],"version-history":[{"count":3,"href":"https:\/\/www.ahosting.net\/blog\/wp-json\/wp\/v2\/posts\/1154\/revisions"}],"predecessor-version":[{"id":1159,"href":"https:\/\/www.ahosting.net\/blog\/wp-json\/wp\/v2\/posts\/1154\/revisions\/1159"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.ahosting.net\/blog\/wp-json\/wp\/v2\/media\/1155"}],"wp:attachment":[{"href":"https:\/\/www.ahosting.net\/blog\/wp-json\/wp\/v2\/media?parent=1154"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ahosting.net\/blog\/wp-json\/wp\/v2\/categories?post=1154"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ahosting.net\/blog\/wp-json\/wp\/v2\/tags?post=1154"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}