Avoiding unintended exposure from the WordPress REST API

Published on by Pat Ramsey, Director of Technology

WordPress 4.7 is about a month old now, and the first bug-fix release, 4.7.1, has come out. With the first dot-one release now available, we’ve reached the point where enterprise adoption begins to pick up and site owners coordinate deployments of the new version. With the rate of adoption on the rise, we want to address one particular feature of 4.7 that has raised a lot of concern: the inclusion of the WP REST API content endpoints in WordPress core itself.

At Crowd Favorite, we’re excited for the endless possibilities the API presents, and look forward to all the ways we can leverage it for our clients and their sites. We believe, though, that enabling this feature and making their site content accessible via the API is a decision that each site owner should make for themselves. To that end, we want to help our partners – and everyone else – make the most informed decisions possible.

To be certain, transferring the REST API from a plugin into WordPress core is a great move. This encourages a greater level of adoption, as well as an increase to the contributing development, simply because it’s no longer a tool that must be installed separately. The reason for concern, for many site owners, is that these new content endpoints are enabled and publicly accessible by default. This creates a secondary, possibly unintended, publication source. Instead of delivering your content over traditional web pages, you’re now also delivering content via the API and its endpoints. What you see in the API is the same content that is publicly accessible via the site itself, but now it takes fewer clicks to retrieve more content that is, by design, machine readable.

One specific area of concern with this is the user’s endpoint, /wp-json/wp/v2/users/. In WordPress 4.7 this endpoint listed all users who have published content on the site, along with their author profile information. Again, this is the same level of information WordPress already makes publicly available. The difference is that the REST API delivers all of this information within a single HTTP request, making it much easier for third-parties to gather user information from a site. For those concerned with security, this raises an issue around user enumeration. A list of valid usernames could easily be gleaned from a single API call to the user’s endpoint. The WordPress 4.7.1 release modified this, for the better, so the user’s endpoint only lists users who have authored published content types explicitly set to be visible within the API.

Still, for many enterprise clients, it’s the unintended and automatic distribution of content through the new API, combined specifically with the ease of gathering usernames, that make this feature a security concern.

Securing a website is best accomplished through multiple layers of effort. For your site, this may include enforcing strong user passwords, requiring two-factor authentication, keeping both WordPress and installed plugins up-to-date with the latest security releases, and using a reliable, managed host who facilitates maintenance of the underlying server infrastructure. Each of these aspects are important steps towards keeping a site, its owners, and its visitors safe. Each layer is designed to make it a bit more difficult for someone to attack and compromise your site. So why, then, would you make it easier for a bad actor to plan their attack by providing a list of usernames in one easy-to-access location?

Thankfully, there are several ways to address this concern. One option that has been discussed is to simply remove the user’s endpoint. While this is an easy thing to do technically speaking, it does introduce a new degree of complexity to the site. Additionally, disabling a core endpoint could become problematic in the near future for apps or services that may depend on it (including core WordPress functionality itself). Rather than add complexity, or create potential issues for unaware apps or services, there is a simpler solution: require authentication for REST API access.

Restricting API access to authenticated users makes the most sense for a few reasons. First and foremost, it leaves the API completely intact while also eliminating anonymous, public access. The easiest way to accomplish this change is to install and activate a small plugin named Disable REST API. If you use a security plugin, such as iThemes Security or WordFence, you may find the plugin already includes a setting that performs this same action. From a development perspective, each of these solutions is calling a series of core WordPress filters designed to disable public discoverability for the API endpoints and prevent non-authenticated user access.

Should you disable public access to the REST API? Like all large, overarching decisions like this, the answer is “it depends.”

As we expressed earlier, we believe each site owner should decide how to handle inclusion of the REST API themselves. Generally speaking, we believe the API is a wonderful addition and should remain enabled, accessible, and poses no real security risk to most websites. On the other hand, if you have a specialized site and exposing your public data in a different way could damage the overall brand or site experience, or are positive that you’ll never want a third-party consuming your site data via an API, then leaving the API accessible to non-authenticated users is the right choice.