question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

CORS middleware behaviour change - dropping Access-Control-Allow-Headers header

See original GitHub issue

In the pre CORSPolicy implementation, if a preflight request included a header in Access-Control-Request-Headers that was not permitted by the CORS configuration, the CORS middleware would return a Access-Control-Allow-Headers header with the list of allowed headers. In the current implementation (so 0.23.3+, and not sure the equivalent for 1.0.0-x and 0.22.x) if the request header has more fields than are allowed, the response header gets dropped.

Example in 0.23.4

import cats.effect.IO
import cats.effect.unsafe.implicits._
import org.http4s.server.middleware.CORS
import org.http4s._
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
import org.typelevel.ci.CIStringSyntax

class CORSTest extends AnyFlatSpec with Matchers {

  val cors = CORS.policy.withAllowHeadersIn(Set(ci"Foo", ci"Bar")).withAllowMethodsAll

  val routes = cors(HttpRoutes.pure[IO](Response[IO]())).orNotFound

  val request =
    Request[IO](
      method = Method.OPTIONS,
      headers = Headers(
        Header.Raw(ci"Origin", "http://example.com"),
        Header.Raw(ci"Access-Control-Request-Headers", "foo, faz"), //faz not allowed, foo is 
        Header.Raw(ci"Access-Control-Request-Method", "POST")
      )
    )

//FAILS
  it should "have an Access-Control-Allow-Headers header" in {
    //this header should be present and have value "Foo,Bar", but is missing
    routes(request).unsafeRunSync().headers.get(ci"Access-Control-Allow-Headers").isDefined shouldBe true
  }
}

and here is a worksheet using the old CORSConfig implementation where we see that the header is still returned under these circumstances https://scastie.scala-lang.org/6WjBVGOVRRy3vYGv4YZ6Qg

Issue Analytics

  • State:open
  • Created 2 years ago
  • Comments:7 (7 by maintainers)

github_iconTop GitHub Comments

1reaction
rossabakercommented, Oct 4, 2021

The CORS spec is very frustrating. The old one covered the server side in detail, but the replacement says next to nothing.

In the old spec, in Step 6, it says:

If any of the header field-names is not a ASCII case-insensitive match for any of the values in list of headers do not set any additional headers and terminate this set of steps.

where “header field-names” is from Access-Control-Request-Headers and “list of headers” are the supported headers we would return in Access-Control-Allow-Headers. So per the old spec, I think the current behavior is correct. I also referenced popular implementations from other languages while working on the CVE, and I don’t think we’re on an island here.

That said, I’m struggling with why it should be a guessing game. Because the allowed headers can be unbounded but wildcards are incompatible with other settings, some CORS implementations exploit the matching rule to return a finite set of headers based on reflecting the request. Aside from that, I don’t know why it shouldn’t just return the full set of headers. But the spec authors have usually thought deeper than me. I’d be interested to dig up their reasons.

0reactions
rossabakercommented, Oct 4, 2021

From the linked ticket, it looks like the relaxation is intentional in the new spec. I think that puts Option A back on the table. The question is if anybody prefers the Old Spec behavior vs. the Old Http4s behavior.

Read more comments on GitHub >

github_iconTop Results From Across the Web

No 'Access-Control-Allow-Origin' header is present on the ...
This answer covers a lot of ground, so it's divided into three parts: How to use a CORS proxy to avoid “No Access-Control-Allow-Origin ......
Read more >
Enable Cross-Origin Requests (CORS) in ASP.NET Core
There are three ways to enable CORS: In middleware using a named policy or default policy. Using endpoint routing. With the [EnableCors] ...
Read more >
koajs/cors: Cross-Origin Resource Sharing(CORS) for koa
Quick start. Enable cors with default options: origin: request Origin header; allowMethods: GET,HEAD,PUT,POST,DELETE,PATCH.
Read more >
3 Ways to Fix the CORS Error — and How the Access-Control ...
The proxy uses express middleware to apply a Access-Control-Allow-Origin: * header to every response from the server. At its own jokes/random ...
Read more >
Your Complete API Gateway and CORS Guide
I won't provide any information on CORS headers for WebSocket API as it isn't ... Access-Control-Allow-Headers: true method.response.header.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found