Skip to content

Fix: throw error when credentials=true with origin='*' - #413

Open
jiafeimao0p wants to merge 1 commit into
expressjs:masterfrom
jiafeimao0p:fix/credentials-origin-validation
Open

jiafeimao0p wants to merge 1 commit into
expressjs:masterfrom
jiafeimao0p:fix/credentials-origin-validation

Conversation

@jiafeimao0p

Copy link
Copy Markdown

Summary

According to the CORS specification, using wildcard * in Access-Control-Allow-Origin header is forbidden when Access-Control-Allow-Credentials is set to true.

This fix adds validation that throws an error when both options are set, following the fetch spec: https://fetch.spec.whatwg.org/#cors-protocol-and-credentials

Problem

Currently, the cors middleware allows setting credentials: true with origin: '*', which violates the CORS standard and causes browsers to reject the request.

Solution

Added a validateCredentialsAndOrigin() function that throws an error when both credentials is true and origin is '*'.

Changes

  • lib/index.js: Added validateCredentialsAndOrigin() function and call it in the cors middleware
  • test/test.js: Added test cases for the new validation

Testing

Added test cases:

  • Verifies error is thrown when credentials=true and origin='*'
  • Verifies origin='*' works normally when credentials=false

Fixes #333

According to CORS specification, using wildcard '*' in
Access-Control-Allow-Origin header is forbidden when
Access-Control-Allow-Credentials is set to true.

This fix adds validation that throws an error when both
options are set, following the fetch spec:
https://fetch.spec.whatwg.org/#cors-protocol-and-credentials

Fixes expressjs#333

@kilisamemarisaaa kilisamemarisaaa left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found a runtime error-propagation issue in the proposed validation.

validateCredentialsAndOrigin() throws from cors() after the options callback has been entered. With the supported dynamic-options form, the callback can run asynchronously, so the Express middleware stack has already returned and cannot catch that throw. A minimal reproduction on Node 24 with this PR is:

const express = require('express')
const request = require('supertest')
const cors = require('./')
const app = express()

app.use(cors((req, cb) => process.nextTick(() => cb(null, {
  origin: '*',
  credentials: true
}))))
app.get('/', (req, res) => res.send('ok'))
process.once('uncaughtException', err => console.log('UNCAUGHT', err.message))
request(app).get('/')

It prints UNCAUGHT Cross-origin requests are not allowed ... and the request never reaches an Express error handler. Static options happen to be synchronous and are caught by Express, which makes this path easy to miss. Please validate before the asynchronous boundary or propagate the validation failure through next(err)/the options callback, and add a regression test using an asynchronous options callback plus an error handler.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CORS requests with credentials should forbid *

3 participants