Browser API CORS Allowlist and Credential Exposure Gate
Pricing
from $10.00 / 1,000 cors gate run starts
Browser API CORS Allowlist and Credential Exposure Gate
Sends a real OPTIONS preflight and a real cross-origin GET from each origin that you name, against each API path that you name. Reports which origins the API accepts, which accept credentials, and every violation class: wildcard with credentials, origin r
Pricing
from $10.00 / 1,000 cors gate run starts
Rating
0.0
(0)
Developer
kingii98
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
Send a real preflight request and a real cross-origin request from each origin that you name, against each API path that you name. The report says which origins your API accepts, which of them may send credentials, and what changed since the last run.
Every incumbent in the store grades response headers on one GET request. This Actor sends an
OPTIONS preflight from a named origin, so it finds the two faults that a header grade cannot see:
an API that copies any origin into Access-Control-Allow-Origin while it allows credentials, and
an API that accepts an origin which you never wanted.
HTTP only. No browser, no proxy and no external database.
What the Actor sends
For each origin and path pair:
OPTIONS <path>withOrigin,Access-Control-Request-MethodandAccess-Control-Request-Headers. This is the preflight that a browser sends.GET <path>withOrigin. This is the real cross-origin request.
The Actor never sends a state-changing request. POST, PUT and DELETE are only named in
the preflight and compared against Access-Control-Allow-Methods. The response body is never read;
only the headers carry the CORS policy.
When a path reflects the sent origin, the Actor sends two more calls from a control origin
(https://cors-probe-reflection-check.example.net). That pair separates a real origin reflection
from a static wildcard and from a static allow list that happens to hold your origin.
Input
Run it with empty input to see the default fixture against a stable public API. That target
answers with Access-Control-Allow-Origin: *, so the fixture run ends with a failed gate and
one deny_list_origin_accepted record for each deny-list origin. The run itself succeeds: a gate
verdict is a result, never a failed run.
| Field | Default | Meaning |
|---|---|---|
apiBaseUrl | https://api.github.com | The base URL of an API that you own or may test. Private, loopback and reserved addresses are refused. |
paths | ["/", "/rate_limit"] | 1 to 25 endpoint paths. |
expectedAllowOrigins | ["https://app.example.com"] | Origins that must be accepted. |
expectedDenyOrigins | ["https://evil.example.com", "null", "http://attacker.example"] | Origins that must be refused. |
includeSubdomainProbe | true | Add https://cors-probe.<your domain> to the deny list. |
methods | ["GET", "POST", "PUT", "DELETE"] | Methods to request in the preflight. The first one is sent in Access-Control-Request-Method. |
requestHeaders | ["authorization", "content-type"] | Headers to request in the preflight. |
authorizationStatement | see schema | Free text. You confirm ownership. The Actor writes it to the run log and to the summary. |
trackMatrix | true | Keep the verdict matrix in the key-value store and report the diff. |
matrixKey | "" | Empty means: derive the key from the base URL. |
timeoutSeconds | 15 | Timeout of one request. |
maxConcurrency | 5 | Pairs probed at the same time. |
maxRequests | 900 | Hard bound on the run. |
maxRedirects | 0 | A browser preflight does not follow a redirect. Each hop that the Actor follows takes the public-address test again. |
An origin that stands in both lists is treated as an allow-list origin.
Output
The dataset holds four record types.
probe — one row for each origin and path pair: origin, path, method,
preflightStatus, actualStatus, allowOrigin, reflectsOrigin, allowCredentials,
allowedMethods, allowedHeaders, missingMethods, missingHeaders, varyOrigin, maxAge,
accepted, changeSinceLastRun and a verdict of expected_allow_ok, expected_deny_ok,
unexpected_allow or unexpected_deny.
violation — the violation list. Each item carries a named class:
| Class | Severity | Meaning |
|---|---|---|
origin_reflection_with_credentials | critical | The API copies the sent origin and allows credentials. A control origin was reflected too, so any site can read the answer of a signed-in user. |
wildcard_with_credentials | high | Access-Control-Allow-Origin: * together with Access-Control-Allow-Credentials: true. A browser refuses that pair, so your own credentialed call fails. |
null_origin_accepted | high | The API accepts the origin value null, which a sandboxed frame sends. |
deny_list_origin_accepted | high | An origin of your deny list is accepted. |
allow_list_origin_refused | medium | An origin of your allow list is refused, so your application breaks. |
missing_vary_origin | low | An origin-dependent Access-Control-Allow-Origin without Vary: Origin. A shared cache can then give one origin the header of another. |
The three classes that describe the endpoint itself (wildcard_with_credentials,
origin_reflection_with_credentials, missing_vary_origin) are written once for each path. The
three classes that describe one pair are written for each pair.
change — the diff against the last run: became_accepted, became_refused,
credentials_enabled or credentials_disabled. The first run writes the matrix and reports no
diff.
summary — one record with gatePass, the counts, status, note and your
authorizationStatement. The gate passes when there is no violation, no failed pair and no
skipped pair.
A business verdict is never a failed run. A failed gate, a refused target, an unreachable API and zero violations all end with a SUCCEEDED run, a dataset record and a status message. Only a malfunction, for example an input that cannot be parsed, gives a failed run.
Pay per event
| Event | Unit | Price |
|---|---|---|
cors-gate-run-start | one run | USD 0.01 |
origin-endpoint-probed | one origin and path pair, preflight plus actual request | USD 0.003 |
violation-recorded | one confirmed violation in the violation list | USD 0.03 |
A pair that was skipped by the request bound, and a pair that never reached the API, are not charged. A matrix of 8 origins by 25 paths is 200 pairs, which is USD 0.60 plus the run start and the violations.
Repeat use
Run it once after each deployment of the API or of the gateway, through your build pipeline, and
once a week as a regression run. CORS policy lives in gateway configuration, so it drifts silently
at each infrastructure change. The change records name the drift.
Authorization
The Actor sends requests to a live API. Run it only against an API that you own, or that you are
authorized to test. State that in authorizationStatement; the Actor keeps the text with the
report.
Development
uv syncuv run pytestuv run ruff check .


