Cross-Origin Resource Sharing (CORS)

What is CORS?

Web pages, say like, can always request resources from another web page as long as it comes from the same origin (this includes protocol, domain, and port). This same origin policy helps prevent malicious behavior since data circulates only from within the domain.

But what if the resources you need are only available elsewhere? This is where CORS come into play. It allows you to access resources or to navigate to another server. This is helpful especially when loading images, scripts, stylesheets, etc. CORS requests are done by using standard HTTP methods such as GET, PATCH, POST, PUT, and DELETE and are implemented using HTTP headers.

HTTP Request Headers:

  • Origin

  • Access-Control-Request-Method

  • Access-Control-Request-Headers

HTTP Response Headers:

  • Access-Control-Allow-Origin

  • Access-Control-Allow-Credentials

  • Access-Control-Expose-Headers

  • Access-Control-Max-Age

  • Access-Control-Allow-Methods

  • Access-Control-Allow-Headers

Access-Control-Allow-Origin allows servers to specify how their resources are shared externally. Many times, this header will be set to * pertaining to any external domain. It could be a list of domains or it could even be set to null.

Most servers only allow GET requests as to avoid any intention of maliciously editing or deleting assets. However, such requests are not automatically dropped by the server. It first undergoes a preflight test in order to determine what methods are allowed.

Pre-flight Test

  1. It first sends an OPTIONS request:

    OPTIONS /resource HTTP/1.1
    Access-Control-Request-Method: DELETE
  2. The server responds:

    HTTP/1.1 200 OK
    Access-Control-Allow-Origin: *
    Access-Control-Allow-Method: DELETE, GET

After the pre-flight test, the original request is then handled.

  1. Deleting a resource:

    DELETE /resource HTTP/1.1
    Access-Control-Request-Method: DELETE
  2. The server responds:

    HTTP/1.1 200 OK
    Access-Control-Allow-Origin: *

Since the DELETE method was allowed after checking during the pre-flight test, the resource was successfully deleted. Other headers automatically added by the browser are omitted from the example above.

Common Misconfigurations

  • Access-Control-Allow-Credentials is set to true:

    Credentials are often stored in cookies and cookies are used to maintain our sessions or what the browser uses to indicate that we are currently logged in. Its value is mostly unique to our own and this header enables credential transmission which is bad new especially for websites susceptible to [Cross-Site Scripting (XSS)](

    This would only be exploitable if Access-Control-Allow-Origin is not set to a wildcard (*) even if the a wildcard was used to cover a website's subdomains (e.g. *

    Exposing your website to everyone and used along with this header the console would return Cannot use wildcard in Access-Control-Allow-Origin when credentials flag is true. This could be a work around but this is still bad practice.

  • Access-Control-Allow-Origin: null

    Hostile documents could be crafted and sent with a Origin: null header and it would be accepted since serialization of the Origin of files are defined to be null.

    This should not be used.

  • Don't give unneeded methods in Access-Control-Allow-Method

    DELETE, PATCH, POST, and PUT could be used to alter or remove a site's assets/resources and even trigger further unwanted actions.

  • Giving access to everyone -- Access-Control-Allow-Origin: *

    Perhaps adding specific websites to a white list might be advisable if resources contain somewhat sensitive content.

    Or perhaps limiting accessible subdomains and endpoints would prove to be more secure but this would require different configurations.