Skip to content

Commit cebf4e8

Browse files
authored
fix(cors): avoid setting Access-Control-Allow-Origin if there is no matching origin (#3510)
1 parent 3311664 commit cebf4e8

File tree

2 files changed

+39
-6
lines changed

2 files changed

+39
-6
lines changed

src/middleware/cors/index.test.ts

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@ describe('CORS by Middleware', () => {
3434

3535
app.use('/api5/*', cors())
3636

37+
app.use(
38+
'/api6/*',
39+
cors({
40+
origin: 'http://example.com',
41+
})
42+
)
3743
app.use(
3844
'/api6/*',
3945
cors({
@@ -83,7 +89,10 @@ describe('CORS by Middleware', () => {
8389
})
8490

8591
it('Preflight with options', async () => {
86-
const req = new Request('https://localhost/api2/abc', { method: 'OPTIONS' })
92+
const req = new Request('https://localhost/api2/abc', {
93+
method: 'OPTIONS',
94+
headers: { origin: 'http://example.com' },
95+
})
8796
const res = await app.request(req)
8897

8998
expect(res.headers.get('Access-Control-Allow-Origin')).toBe('http://example.com')
@@ -105,6 +114,15 @@ describe('CORS by Middleware', () => {
105114
expect(res.headers.get('Access-Control-Allow-Credentials')).toBe('true')
106115
})
107116

117+
it('Disallow an unmatched origin', async () => {
118+
const req = new Request('https://localhost/api2/abc', {
119+
method: 'OPTIONS',
120+
headers: { origin: 'http://example.net' },
121+
})
122+
const res = await app.request(req)
123+
expect(res.headers.has('Access-Control-Allow-Origin')).toBeFalsy()
124+
})
125+
108126
it('Allow multiple origins', async () => {
109127
let req = new Request('http://localhost/api3/abc', {
110128
headers: {
@@ -116,21 +134,28 @@ describe('CORS by Middleware', () => {
116134

117135
req = new Request('http://localhost/api3/abc')
118136
res = await app.request(req)
119-
expect(res.headers.get('Access-Control-Allow-Origin')).toBe('http://example.com')
137+
expect(
138+
res.headers.has('Access-Control-Allow-Origin'),
139+
'An unmatched origin should be disallowed'
140+
).toBeFalsy()
120141

121142
req = new Request('http://localhost/api3/abc', {
122143
headers: {
123144
Referer: 'http://example.net/',
124145
},
125146
})
126147
res = await app.request(req)
127-
expect(res.headers.get('Access-Control-Allow-Origin')).toBe('http://example.com')
148+
expect(
149+
res.headers.has('Access-Control-Allow-Origin'),
150+
'An unmatched origin should be disallowed'
151+
).toBeFalsy()
128152
})
129153

130154
it('Allow different Vary header value', async () => {
131155
const res = await app.request('http://localhost/api3/abc', {
132156
headers: {
133157
Vary: 'accept-encoding',
158+
Origin: 'http://example.com',
134159
},
135160
})
136161

@@ -169,7 +194,11 @@ describe('CORS by Middleware', () => {
169194
})
170195

171196
it('Should not return duplicate header values', async () => {
172-
const res = await app.request('http://localhost/api6/abc')
197+
const res = await app.request('http://localhost/api6/abc', {
198+
headers: {
199+
origin: 'http://example.com',
200+
},
201+
})
173202

174203
expect(res.headers.get('Access-Control-Allow-Origin')).toBe('http://example.com')
175204
})

src/middleware/cors/index.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,15 @@ export const cors = (options?: CORSOptions): MiddlewareHandler => {
6868

6969
const findAllowOrigin = ((optsOrigin) => {
7070
if (typeof optsOrigin === 'string') {
71-
return () => optsOrigin
71+
if (optsOrigin === '*') {
72+
return () => optsOrigin
73+
} else {
74+
return (origin: string) => (optsOrigin === origin ? origin : null)
75+
}
7276
} else if (typeof optsOrigin === 'function') {
7377
return optsOrigin
7478
} else {
75-
return (origin: string) => (optsOrigin.includes(origin) ? origin : optsOrigin[0])
79+
return (origin: string) => (optsOrigin.includes(origin) ? origin : null)
7680
}
7781
})(opts.origin)
7882

0 commit comments

Comments
 (0)