Hidden Assumptions in cors

7 assumptions this code never checks · 1 critical · spanning Domain, Contract, Ordering, Environment

Every codebase relies on things it never checks. Most of them are routine. CodeSea looked at expressjs/cors and picked out the few most likely to cause trouble — explained plainly, with what to do about each. The full list is just below.

Most of what this code assumes is routine. These 2 are the ones most likely to cause trouble here — in plain terms, with what to do about each. The rest are minor; they're under "Show everything".

Worth your attention first

If you turn on both 'allow any website' and 'allow cookies/login credentials' at the same time, browsers will block every single request — it's a rule browsers enforce strictly. The server will look like it's working fine in your logs, but users in the browser get a confusing access error. This is a very common misconfiguration and there is no warning anywhere in the tool to stop you.

What to do: If you need cookies or login sessions to work cross-origin, you must also specify exactly which website is allowed — not 'any website' — and the tool will not remind you of this, so double-check your settings before going live.

Worth a check

By default, if you don't tell the tool which specific request headers are allowed, it just says 'yes' to whatever any browser asks for. This means a page from another website could ask permission to send unusual or sensitive headers, and your server will approve it automatically without you realising. Most people never configure this setting and never notice.

What to do: Explicitly list the headers your app actually needs in the configuration rather than relying on the default mirror-everything behavior, especially if your app handles sensitive data.

Show everything (5 more)
Contract

Any request that uses the OPTIONS method — including ones from API testing tools, health checkers, or apps doing capability discovery — gets intercepted and immediately answered by this tool, never reaching your own code. If you have written any logic to handle OPTIONS requests yourself, it will never run by default.

What to do: If you have routes that need to respond to OPTIONS requests with custom logic, enable the 'pass OPTIONS through' setting so the tool does not intercept them.

lib/index.js:corsWithOptions
Ordering

If you set up the tool once and later try to change which websites are allowed by modifying the settings object your code holds onto, nothing will change — the tool already copied those settings when it started and ignores later changes. Developers expecting live control over access rules will be silently ignored.

What to do: To change CORS rules at runtime, use the dynamic function form when setting up the tool, rather than trying to modify the original settings object after the fact.

lib/index.js:cors (exported factory)
Domain

The allowed-origins list does an exact character-for-character comparison. A tiny difference — like an extra slash at the end, or uppercase letters in the web address — will cause the tool to reject a browser's request even if the address is effectively the same website. This produces a silent access error that looks just like a genuine block.

What to do: Make sure the origin strings in your allowed list match exactly how browsers will send them — check for trailing slashes and letter case, or use a regular expression pattern if you need flexible matching.

lib/index.js:isOriginAllowed
Contract

If a request arrives without any 'which website is this from' information — which happens with direct server-to-server calls or certain testing tools — and you have configured the tool to reflect the requester's address back, the response will contain a nonsense value instead of a real web address. This is usually harmless but can confuse security scanning tools.

What to do: If your API serves both browser clients and server-to-server calls, use a function-based origin check that handles the case where no origin information is present in the request.

lib/index.js:configureOrigin
Environment

This tool is built specifically for one family of web frameworks. If someone tries to use it with a different framework — or in a plain web server without the expected framework underneath — it will crash with a confusing technical error about a missing method rather than a clear message saying it is incompatible.

What to do: Check that your web server framework is Express or Connect (or a framework that wraps one of them) before adding this tool; if you are using a different framework, look for a CORS package built specifically for it.

lib/index.js:corsWithOptions

See the full structural analysis of cors: the pipeline, data models, and system behavior that put these assumptions in context.

Full analysis of expressjs/cors →

Frequently Asked Questions

What does cors assume that could break in production?

The one most likely to cause trouble: If you turn on both 'allow any website' and 'allow cookies/login credentials' at the same time, browsers will block every single request — it's a rule browsers enforce strictly. The server will look like it's working fine in your logs, but users in the browser get a confusing access error. This is a very common misconfiguration and there is no warning anywhere in the tool to stop you. What to do: If you need cookies or login sessions to work cross-origin, you must also specify exactly which website is allowed — not 'any website' — and the tool will not remind you of this, so double-check your settings before going live.

How many hidden assumptions does cors have?

CodeSea found 7 assumptions cors relies on but never validates, 1 of them critical, spanning Domain, Contract, Ordering, Environment. Most are routine — the analysis flags the two or three most likely to actually bite.

What is a hidden assumption?

Something the code depends on but never checks: a data shape, an ordering, an environment condition, a scale limit, or a contract with another service. It holds until the world it runs in changes, then fails silently.