Security Tools

CORS Policy Tester

Test Cross-Origin Resource Sharing policies and identify misconfigurations.

intermediate5-10 minutesRuns in your browser

Interactive workspace

Inputs stay on your device — nothing is sent to our servers unless you choose to share.

Client-side only

Simulated request

Request headers (non-simple triggers preflight)

Server CORS policy

Allowed origins

https://app.example.comhttps://admin.example.com

Allowed headers

Content-TypeAuthorizationX-Requested-With

Expose headers

Live evaluation

Request allowed

Preflight would succeed — cross-origin request allowed.

Preflight (OPTIONS) required · would pass

Access-Control-Allow-Origin

ok
https://app.example.com

Echoes the request origin or * when permitted.

Access-Control-Allow-Credentials

ok
true

Whether cookies and Authorization headers are included.

Access-Control-Allow-Methods

ok
GET, POST, PUT, DELETE, OPTIONS

Methods permitted for cross-origin requests.

Access-Control-Allow-Headers

ok
Content-Type, Authorization, X-Requested-With

Request headers allowed during preflight.

Access-Control-Expose-Headers

ok
X-Request-Id

Headers the browser may expose to frontend JavaScript.

Access-Control-Max-Age

ok
86400

How long preflight results may be cached (seconds).

Web server configuration

Copy-ready snippets generated from your policy — includes OPTIONS preflight where applicable.

server/location block with OPTIONS preflight handling.· nginx.conf snippet

# nginx — multiple origins (echoes Origin when allowed)
# Place the map in http { } context (outside server { })
map $http_origin $cors_allow_origin {
    default "";
    "https://app.example.com" $http_origin;
    "https://admin.example.com" $http_origin;
}

server {
    location / {
        if ($request_method = OPTIONS) {
            add_header Access-Control-Allow-Origin $cors_allow_origin;
            add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS";
            add_header Access-Control-Allow-Headers "Content-Type, Authorization, X-Requested-With";
            add_header Access-Control-Max-Age 86400;
            add_header Access-Control-Allow-Credentials "true";
            add_header Content-Length 0;
            add_header Content-Type "text/plain; charset=utf-8";
            return 204;
        }

        add_header Access-Control-Allow-Origin $cors_allow_origin always;
    add_header Access-Control-Allow-Credentials "true" always;
        add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" always;
        add_header Access-Control-Allow-Headers "Content-Type, Authorization, X-Requested-With" always;
        add_header Access-Control-Max-Age 86400;
        add_header Access-Control-Expose-Headers "X-Request-Id"; always;

        # ... your proxy_pass / root / etc.
    }
}

Multiple origins with credentials require echoing the request Origin header — the Nginx map and Express callback patterns handle this dynamically.

Try a scenario

How CORS works

Browsers enforce Cross-Origin Resource Sharing before JavaScript can read cross-origin responses. Non-simple requests trigger a preflight OPTIONS call. Use the web server tabs above to deploy the generated policy on Nginx, Apache, Caddy, Express, or Cloudflare Workers.

Misconfigured CORS is a common finding in web assessments. Never use * with credentials, and always enumerate trusted origins explicitly for authenticated APIs.

Documentation

How to use this tool, practical use cases, and technical notes.

The CORS Policy Tester is organized into two panels: the Simulated Request (what the browser would send) and the Server CORS Policy (what your server is configured to allow). The live evaluation panel updates in real time as you change any setting.

Step 1 — Configure the Simulated Request

The left panel represents the cross-origin HTTP request being made from a browser. Configure:

Request Origin

Enter the origin from which the request is being made — the scheme, hostname, and port of the page making the request. Examples:

Scenario

Request Origin to Enter

Production frontend app

https://app.example.com

Admin dashboard

https://admin.example.com

Local development (HTTPS)

https://localhost:3000

Local development (HTTP)

http://localhost:3000

Sandboxed iframe or file://

null

Attacker site (for testing)

https://evil.attacker.com

HTTP Method

Select the HTTP method the request will use: GET, POST, PUT, PATCH, DELETE, or HEAD.

Method

Preflight Required?

Notes

GET

❌ No (if no custom headers)

Simple request

POST with simple Content-Type

❌ No

Only text/plain, multipart/form-data, application/x-www-form-urlencoded

POST with application/json

✅ Yes

Non-simple Content-Type triggers preflight

PUT

✅ Yes

Always non-simple

PATCH

✅ Yes

Always non-simple

DELETE

✅ Yes

Always non-simple

HEAD

❌ No

Simple method

Request Headers

Toggle the headers your request will include. Any header beyond the CORS-safe list triggers a preflight:

Header

Triggers Preflight?

Common Use

Content-Type: application/json

✅ Yes

REST API JSON bodies

Authorization

✅ Yes

Bearer tokens, Basic auth

X-Requested-With

✅ Yes

AJAX identification

Accept

❌ No

CORS-safe header

X-CSRF-Token

✅ Yes

CSRF protection tokens

X-Api-Key

✅ Yes

API key authentication

Step 2 — Configure the Server CORS Policy

The right panel represents your server's CORS response headers. This is the policy you are designing or testing.

Allowed Origins

Add the exact origins your server will permit. The tool supports four origin modes:

Mode

Configuration

When to Use

Explicit list

https://app.example.com, https://admin.example.com

Production APIs with known frontends (recommended)

Wildcard (*)

Select * from dropdown

Public read-only APIs with no authentication

Localhost variants

localhost:3000 (HTTP or HTTPS)

Local development environments

Null

Select null

Sandboxed iframe testing only; never production

Allowed Methods

Toggle which HTTP methods your server permits for cross-origin requests. As a rule:

  • List only the methods your API actually uses

  • Always include OPTIONS if you handle preflight manually (most frameworks handle this automatically)

  • Avoid listing DELETE or PUT on public APIs unless required

Allowed Headers

Toggle which request headers the server will accept from cross-origin requests. Only headers listed here will be permitted in preflight and actual requests.

Preflight Cache (Max-Age)

Set how long browsers will cache the preflight response, avoiding repeated OPTIONS calls:

Max-Age Value

Seconds

Browser Behavior

Not set

0

Preflight sent on every request

1 hour

3,600

Cached for 1 hour per browser tab

24 hours

86,400

Cached for 1 day — good production default

7 days

604,800

Maximum practical cache; use only for stable APIs

Note: Chrome caps preflight caching at 2 hours (7,200 seconds) regardless of the Max-Age value. Firefox respects longer values up to 86,400 seconds.

Expose Headers

Headers listed here are made available to JavaScript via response.headers.get(). Without being listed here, response headers are hidden from frontend code even if the request succeeds:

Header

Why Expose It

X-Request-Id

Frontend logging and distributed tracing

X-Total-Count

Pagination — total record count for list endpoints

Content-Disposition

File download — filename from server

Link

Pagination links (GitHub API pattern)

Allow Credentials

Toggle whether the server sends Access-Control-Allow-Credentials: true. This controls whether the browser includes cookies, HTTP authentication, or TLS client certificates in the request.

⚠️ Critical constraint: When credentials are enabled, Access-Control-Allow-Origin must be a specific origin, not *. This is enforced by all modern browsers. The tool flags this as an invalid configuration if you attempt to combine both.

Step 3 — Read the Live Evaluation

The evaluation panel shows the outcome of your configuration in real time:

Result

Meaning

Request allowed

The cross-origin request would succeed

Preflight would succeed

The OPTIONS preflight passes, and the actual request would be allowed

⚠️ Preflight required

A preflight OPTIONS call will be sent before the actual request

Request blocked

The browser would block this request based on the current policy

Invalid configuration

The policy contains a combination that browsers will reject (e.g., * + credentials)

The panel also shows the exact values that would appear in each CORS response header, so you can verify the output before deploying.

Step 4 — Use the Pre-Built Scenarios

The "Try a scenario" section at the bottom of the tool loads common CORS configurations with a single click:

Scenario

What It Demonstrates

Allowed API call

A correctly configured policy that permits a specific authenticated origin

Blocked origin

A request from an untrusted origin that the policy correctly blocks

Public wildcard

A wildcard * policy suitable for a public, unauthenticated API

Invalid: * + credentials

The dangerous combination of wildcard origin with credentials enabled

Use the "Invalid: * + credentials" scenario to understand exactly why this combination is rejected by browsers and why some backends that return both headers are still vulnerable.

Step 5 — Copy the Server Configuration Snippet

Once your policy is correctly configured and the evaluation shows your desired result, navigate to the "Web server configuration" tabs and copy the generated snippet for your server platform:

Platform

What Gets Generated

HTTP headers

Raw header values only (for any platform)

Nginx

map + server { location } block with OPTIONS preflight handler

Apache

.htaccess or <VirtualHost> directives with mod_headers

Caddy

Caddyfile header directives

Express.js

Node.js middleware using the cors npm package

Cloudflare Worker

JavaScript Worker script handling CORS at the edge

Click "Copy snippet" and paste directly into your configuration file. The generated code includes inline comments explaining each directive.

Step 6 — Reset and Test New Scenarios

Click "Reset" to return to the default configuration and start a new test. This is useful when testing multiple API endpoints with different CORS requirements, or when walking through attack scenarios to understand the impact of misconfigurations.