Categories
Programming

WordPress REST Allows Cross-Origin by Default

This is not a red alert. It’s not a bug. I just found it interesting.

If you make a request to the REST API built into WordPress and you pass in an Origin header, the response will contain an Access-Control-Allow-Origin header with the same value. This response header is part of CORS (Cross-Origin Resource Sharing), which is a feature of browsers that’s meant to protect from executing code from another URL. If the server responds with a different URL, the browser will refuse to complete the request. A typical scenario would be JavaScript running on a page hosted by https://foo.com attempting an Ajax request to https://bar.com. If the Web server at bar.com responds with Access-Control-Allow-Origin: https://foo.com, the browser refuses to complete the request. It’s a sensible default stance.

This came up during a broad security scan of a client Web site. Security scanners notoriously over-report issues, but it’s best to understand the issue before dismissing, even if it’s labeled a “medium” risk. I did some searching and found that this behavior for the WordPress REST API is by design. The reason is that WordPress already imposes a robust security model on the REST API. If an endpoint uses secure information, it must authenticate to a user via a nonce. This is a short-term, randomly-generated token specific to the user. Without the nonce, calls to privileged functionality will fail inside the PHP code. Thus, WordPress purposely subverts the usual CORS approach.

Consequently, WordPress gets out of the way of developers who must implement alternative authentication schemes. It also allows plugins and themes to impose more restrictive requirements. It’s possible to hook into the REST response and set a different Access-Control-Allow-Origin header. This header can only contain a single URL, though. For cases where you have several requesting sites, you’d keep a list and respond with the matching URL if it’s on the approved list.

This topic came up in a WordPress bug report back in 2018 (ticket #45477), and also covered in the REST API FAQs. It’s fortunate that WordPress is Open Source. It makes it easy to see what’s going on and to benefit from the open discussions of bugs, even those from years ago.

Leave a Reply

Your email address will not be published. Required fields are marked *