Cors security
Strict CORS configuration: no wildcard with credentials, allowlist-based origins, sensible preflight cache, minimal exposed headersFrom its SKILL.md
npx -y skills add ShieldNet-360/secure-vibe --skill cors-securityAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 15 stars15 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
5.6 KB, ~1.2k tokens by cl100k_base, as published. Nobody here has run it
CORS Security
Rules (for AI agents)
ALWAYS
- Use an allowlist of origins, not
*. Reflect the incomingOriginheader only when it matches a known entry from configuration (or matches a precompiled regex of operator-controlled hostnames). - If responses include credentials (cookies,
Authorization), setAccess-Control-Allow-Credentials: trueand ensureAccess-Control-Allow-Originis a single specific origin string — never*. - Include
Vary: Originon responses whose body depends on the requestOrigin, so caches don't serve one origin's response to another. - Restrict preflight
Access-Control-Allow-Methodsto the actual methods the endpoint accepts; restrictAccess-Control-Allow-Headersto the actual headers consumed. - Set
Access-Control-Max-Ageto a sensible value (≤ 86400 in production) to amortize preflight latency without locking in a bad allowlist. - Maintain the allowlist in code (or in a config file checked into source), not derived from a database — so attackers can't add their origin by inserting a row.
NEVER
- Set
Access-Control-Allow-Origin: *together withAccess-Control-Allow-Credentials: true. The Fetch spec forbids it for a reason — browsers will refuse the response, but the bigger problem is that an upstream proxy / cache may already have leaked it. - Reflect the
Originheader without an allowlist check (Access-Control- Allow-Origin: <Origin>for every incoming origin). That's the same as*for credentials but with worse caching behavior. - Allow
nullas an Origin.nullis what Chrome sends from sandboxed iframes,data:URIs, andfile://— none of which should have credentialed access to your API. - Allow arbitrary subdomains with a regex like
.*\.example\.com$without considering subdomain takeover. Pin specific subdomains; treat*.example.comas a deliberate decision tied to subdomain ownership controls. - Expose internal headers via
Access-Control-Expose-Headers. Limit to the minimal set the frontend genuinely needs. - Use CORS as authorization. CORS is a browser policy; it does not stop server-to-server, curl, or non-browser clients. Authenticate the request properly.
KNOWN FALSE POSITIVES
- Truly public, unauthenticated APIs (e.g., open data, marketing CDN
endpoints) can legitimately use
Access-Control-Allow-Origin: *without credentials. - Internal admin tools restricted to a private network can use a single fixed origin; the wildcard concern doesn't apply because there are no cross-origin callers.
- A handful of integrations (Stripe.js, Plaid, Auth0) expect specific CORS headers — read each provider's CORS section before relaxing the baseline.
Context (for humans)
CORS is widely misunderstood as a security control. It isn't — it's a
relaxation of the same-origin policy. The security control is
authentication. CORS misconfiguration matters because, when combined with
cookies or Authorization headers, it gives untrusted origins the ability
to make credentialed cross-origin requests and read the response.
This skill is short by design — the matrix of bad combinations is finite and the rules are blunt.
Verify & lock (triaging a finding)
A scanner/review hit is a candidate, not a confirmed bug. Confirm it, fix it, then lock it so it can't come back.
- Confirm it's real (probe the suspect input). Replay a request to the endpoint
with a forged
Originheader the allowlist should reject —Origin: https://evil.example, then separatelyOrigin: null— and send credentials (cookie orAuthorization). A real hit: the response echoesAccess-Control-Allow-Origin: https://evil.example(ornull, or*) together withAccess-Control-Allow-Credentials: true, meaning the attacker's page can read the credentialed response. A false positive: the server omits the ACAO header, returns a fixed trusted origin regardless of input, or sends*with no credentials on a genuinely public endpoint — also watch for*.example.comregexes that match attacker-controlled subdomains, and missingVary: Originon cached responses. - Fix, then lock with a regression test (unit or integration — dev's call): assert that
requests with
Origin: https://evil.exampleandOrigin: nullyield no reflected ACAO (never*paired withAllow-Credentials: true), while a known-good origin from the allowlist is reflected as a single specific value withVary: Originpresent. Commit it to CI so the guard can't be silently dropped in a later refactor.
References
rules/cors_safe_config.json- OWASP CORS Origin Header Scrutiny.
- CWE-942.
- Fetch — CORS protocol.
What ships with it: 2 files
4.4 KB alongside SKILL.md
rules/
- cors_safe_config.json1.8 KB
tests/
- corpus.json2.5 KB