403 Forbidden for OPTIONS Request, Logs Show 200

What is the name of the domain?

example.cdn.mydomain.com

What is the error number?

403

What is the error message?

HTTP/2 403 Content-Type: text/html Access-Control-Allow-Origin: *

What is the issue you’re encountering

Verified that the origin server (S3) responds with 200 for the same request when bypassing Cloudflare. Disabled caching for this specific resource and purged the cache. Added custom firewall rules to explicitly allow the OPTIONS method for the specific path. Tested using a Cloudflare Worker, and the issue was resolved with the following Worker code: addEventListener(‘fetch’, event => { const request = event.request; if (request.method === ‘OPTIONS’) { event.respondWith( new Response(null, { status: 200, headers: { ‘Access-Control-Allow-Origin’: ‘*’, ‘Access-Control-Allow-Methods’: ‘GET, OPTIONS’, ‘Access-Control-Allow-Headers’: ‘Content-Type’, }), }) ); } else { event.respondWith(fetch(request)); } }); However, I want to avoid using Workers due to the high volume of requests.

What steps have you taken to resolve the issue?

Hello Cloudflare Community,

I am encountering a persistent issue where Cloudflare responds with a 403 Forbidden for a CORS preflight OPTIONS request, but the logs show a 200 OK. Interestingly, this issue does not occur when I use a Cloudflare Worker to handle the request, which works perfectly. The resource is hosted on Amazon S3, and when I bypass Cloudflare and hit the S3 endpoint directly, the request works correctly with a 200 response.

Here’s the situation in detail:

The request is made to a subdomain on Cloudflare, and the origin is hosted on S3.
The method used is OPTIONS with Origin, Access-Control-Request-Method, and Access-Control-Request-Headers headers.
Despite Cloudflare showing a 200 OK in the logs, the actual client response is 403 Forbidden.

What are the steps to reproduce the issue?

Make a preflight OPTIONS request to the Cloudflare-protected domain with the appropriate headers:
Origin
Access-Control-Request-Method
Access-Control-Request-Headers
Observe that the response from Cloudflare is HTTP/2 403 Forbidden.
Test the same request directly to the S3 bucket (bypassing Cloudflare), and observe a 200 OK response with the correct CORS headers.

I get a 404:

% curl -X OPTIONS https://b8a.me/resource \
  -H "Origin: https://example.com" \
  -H "Access-Control-Request-Method: POST" \
  -H "Access-Control-Request-Headers: Content-Type, Authorization" \
  -svo /dev/null 2>&1 | egrep "< |> "
> OPTIONS /resource HTTP/2
> Host: b8a.me
> User-Agent: curl/8.7.1
> Accept: */*
> Origin: https://example.com
> Access-Control-Request-Method: POST
> Access-Control-Request-Headers: Content-Type, Authorization
> 
< HTTP/2 404 
< date: Thu, 02 Jan 2025 15:19:53 GMT
< content-type: text/html; charset=UTF-8
< cache-control: no-cache, must-revalidate, max-age=0
< expires: Wed, 11 Jan 1984 05:00:00 GMT
< cf-cache-status: DYNAMIC
< strict-transport-security: max-age=31536000; includeSubDomains; preload
< x-content-type-options: nosniff
< content-security-policy: default-src 'none'; connect-src 'self'; font-src 'self' data:; img-src 'self' data:; prefetch-src 'self'; script-src 'self' 'unsafe-inline' static.cloudflareinsights.com; style-src 'self' 'unsafe-inline'; worker-src blob:; upgrade-insecure-requests; report-uri https://b8a.me/csp
< permissions-policy: camera=()
< referrer-policy: same-origin
< x-frame-options: SAMEORIGIN
< x-xss-protection: 0
< server: cloudflare
< cf-ray: 8fbbbadc1f8cf7c7-LAX
< alt-svc: h3=":443"; ma=86400
< server-timing: cfL4;desc="?proto=TCP&rtt=18167&min_rtt=11841&rtt_var=8185&sent=9&recv=11&lost=0&retrans=0&sent_bytes=2904&recv_bytes=662&delivery_rate=225909&cwnd=254&unsent_bytes=0&cid=9b12886de7779c51&ts=152&x=0"

Server log:
b8a.me [redacted IPv6] [02/Jan/2025:07:19:52 -0800] "OPTIONS /resource HTTP/1.1" 404 66626 gzip, br - - -

This topic was automatically closed after 15 days. New replies are no longer allowed.