VNX-942: Permissive cross-origin (CORS) policy in a Node.js server
Reports a Node.js server that sets Access-Control-Allow-Origin to '*' or to the request's unchecked Origin, calls cors() or registers @fastify/cors with no options, origin: true or an origin callback that accepts everything, or calls NestJS enableCors() with no options or creates the app with cors: true.
| Field | Value |
|---|---|
| Rule ID | VNX-942 |
| Severity | Medium |
| SARIF level | warning |
| Kind | sast |
| Languages | JavaScript / TypeScript |
| CWE | CWE-942 |
| CAPEC | CAPEC-66 |
| ATT&CK | T1190 |
| CWSS vector | CWSS:1.0/TI:M/AP:A/AL:A/IC:N/FC:LT/RP:N/RL:A/AV:I/AS:N/IN:A/SC:A/BI:M/DI:H/EX:M/EC:N/P:C |
| Tags | cors cwe-942 |
| Source | internal/sast/rules/vnx-942.rego |
Overview
VNX-942 maps to CWE-942: Permissive Cross-domain Policy with Untrusted Domains. A server that allows every origin (or reflects whatever Origin it is sent) lets any website read its responses from a visitor’s browser.
What Gets Flagged
res.setHeader('Access-Control-Allow-Origin', '*'); // flagged
res.setHeader('Access-Control-Allow-Origin', req.headers.origin); // flagged: reflected, unchecked
app.use(cors()); // flagged: cors() allows every origin
apiRouter.use(cors({ origin: true })); // flagged
app.use(cors({ origin: (origin, cb) => cb(null, true) })); // flagged: the callback accepts every origin
app.enableCors(); // flagged (NestJS)
NestFactory.create(AppModule, { cors: true }); // flagged (NestJS)
fastify.register(require('@fastify/cors'), { origin: '*' }); // flagged; register(cors) with no options too
Not flagged: a specific origin or an allowlist, a reflected origin checked against an allowlist first, the header sent by client code (setRequestHeader, fetch/axios request headers), test files, comments and string literals that mention the header. This rule owns CORS in JavaScript and TypeScript servers; VNX-SEC-012 covers the same weakness in other languages, in server configuration and in the AWS CDK allowOrigins construct.
Remediation
const allowed = new Set(['https://app.example.com']);
app.use(cors({ origin: (origin, cb) => cb(null, allowed.has(origin)) }));
References
- CWE-942: Permissive Cross-domain Policy with Untrusted Domains
- OWASP: Testing Cross Origin Resource Sharing
Suppressing this rule
Put a nosec comment on the line, or on line 1 to cover the whole file. Use the comment marker of the file’s language (#, //, -- or ;):
# nosec vnx-942
// nosec vnx-942
Or record an ignore rule: vulnetix ignore add --rule vnx-942 --reason "...". See Suppressing findings.