Skip to content

CORS

The toHaveSecureCORS() matcher tests CORS configuration for misconfigurations. Pass a Playwright APIRequestContext and a URL.

import { test, expect } from "@orlalabs/kovar";
test("API has secure CORS", async ({ request }) => {
await expect(request).toHaveSecureCORS("/api/data");
});

The matcher sends preflight requests with untrusted origins and checks for:

CheckSeverity
Reflects untrusted origin with credentialscritical
Wildcard origin (*) with credentialscritical
Wildcard origin (*)high
Reflects untrusted origin without credentialshigh
Wildcard Access-Control-Allow-Headershigh
Allows dangerous methods (PUT, DELETE, PATCH)medium

CWE mappings:

await expect(request).toHaveSecureCORS("/api/data", {
trustedOrigins: ["https://app.example.com"], // origins that should be allowed
dangerousOrigins: ["null", "http://evil.com"], // origins to test against (default: ["null", "http://evil.com"])
});
OptionTypeDescription
trustedOriginsstring[]Origins that should be allowed by the CORS policy
dangerousOriginsstring[]Origins to test against (default: ["null", "http://evil.com"])
urlstringURL to test (defaults to current page URL)
import { test, expect } from "@orlalabs/kovar";
test("CORS audit", async ({ page, security }) => {
await page.goto("/dashboard");
// Inspect findings:
const corsFindings = await security.cors.check();
const critical = corsFindings.filter((f) => f.severity === "critical");
expect(critical).toHaveLength(0);
});
  • CSRF — CORS and CSRF protections work together.
  • Authentication — authentication bypasses can be amplified by CORS misconfigurations.
  • Full Audit — include CORS in a comprehensive audit with checks: ["cors"].
  • Standalone API — use checkCORS() outside Playwright.