Is it safe to fix Access-Control-Allow-Origin (CORS origin) errors with a php header directive?

The question:

I am trying to show a Formidable Pro Form from a WordPress site to the other.
I followed the developer’s API and the REST API, but faced a CORS problem.

Then I found a suggestion on a forum thread suggesting to add this line of code the functions.php of the site where the original form is:

header("Access-Control-Allow-Origin: *");

I tried this code and it worked perfectly fine.

My question is: does this code opens security risks or other vulnerabilities?

The solution seems too simple for a problem that faces many people.

Your input is highly appreciated.

The Solutions:

Below are the methods you can try. The first solution is probably the best. Try others if the first one doesn’t work. Senior developers aren’t just copying/pasting – they read the methods carefully & apply them wisely to each case.

Method 1

Yes, you open your site to being requested via AJAX to any other script in the whole web.

It would be better if you limit the origin to one specific remote domain from which you are consuming the API, like this example:

header("Access-Control-Allow-Origin: http://mozilla.com");

However as the mozilla documentation states, a client can fork the origin, nevertheless limiting the sites a casual user can connect is a deterrent for some attacks.

Even better, you can limit your request to only the methods you really need to allow, the gist is this snippet, and it works for several domains, if you have the $_SERVER['HTTP_ORIGIN'] variable populated:

add_action('rest_api_init', function() {

     /* unhook default function */
     remove_filter('rest_pre_serve_request', 'rest_send_cors_headers');

     /* then add your own filter */
     add_filter('rest_pre_serve_request', function( $value ) {
          $origin = get_http_origin();
          $my_sites = array( 'http://site1.org/', 'http://site2.net', );
          if ( in_array( $origin, $my_sites ) ) {
              header( 'Access-Control-Allow-Origin: ' . esc_url_raw( $origin ) );
          } else {
              header( 'Access-Control-Allow-Origin: ' . esc_url_raw( site_url() ) );
          }
          header( 'Access-Control-Allow-Methods: GET' );

          return $value;
     });
}, 15);

As you can see, this snippet uses the function get_http_origin provided by WordPress, but it will return null or empty, if the key HTTP_ORIGIN is not populated in the $_SERVER array, therefore it’s not available to the PHP script, maybe because it is blocked by the cloudflare proxy you are using. I’d check quickly, with a script with the <?php phpinfo(); ?>, if you have this variable populated.

Maybe the origin site it’s populated in another header by cloudflare, and you could use it in a function hooked to the http_origin filter. If you are lost to this point, edit your original question posting the contents of the _SERVER variable, except your filesystem paths or passwords.

I’d be glad to help.

Method 2

background – browsers are restricting remote access from scripts to only the site from which it was loaded. If this kind of check wasn’t done, while visiting a site X it would have been possible for it to submit data to your gmail account (if you are logged in) without even needing to guess your user and password, because the browser would have sent the proper authentication cookies to gmail.

The CORS “protocol” is there to help you relax this restriction when needed.

So the question that you should ask yourself, is do I need it? On the one hand, I can’t see why would 99% of wordpress sites need it, on the other hand, wordpress cookies are relatively short lived and 99% of wordpress sites are not going to be a target to such a random attack.

I would say, that since the rest API is a mutating one, and have access to private information, you should not use rest api in your solution if you need to enable cors, you better write your own “read only” API.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Comment