Skip to content

Commit 9f17263

Browse files
authored
Merge pull request #588 from ivanvakulov/origin/issue587
Enhance header filtering in getHeadersApplicableToAllResources function to exclude falsy values
2 parents 70cd67a + d0dc70f commit 9f17263

File tree

9 files changed

+110
-0
lines changed

9 files changed

+110
-0
lines changed

src/utils/headers.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ export function getHeadersApplicableToAllResources(headers: SecurityHeaders) {
177177
Object.entries(headers)
178178
.filter(([key]) => appliesToAllResources(key as OptionKey))
179179
.map(([key, value]) => ([getNameFromKey(key as OptionKey), headerStringFromObject(key as OptionKey, value)]))
180+
.filter(([, value]) => Boolean(value))
180181
)
181182
return Object.keys(applicableHeaders).length === 0 ? undefined : applicableHeaders
182183
}

test/fixtures/publicAssets/.nuxtrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
imports.autoImport=true

test/fixtures/publicAssets/app.vue

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<template>
2+
<div>
3+
<NuxtPage />
4+
</div>
5+
</template>
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
export default defineNuxtConfig({
2+
modules: [
3+
'../../../src/module'
4+
],
5+
routeRules: {
6+
'/test/**': {
7+
security: {
8+
headers: {
9+
referrerPolicy: 'no-referrer',
10+
strictTransportSecurity: {
11+
maxAge: 15552000,
12+
includeSubdomains: true,
13+
},
14+
xContentTypeOptions: 'nosniff',
15+
xDownloadOptions: 'noopen',
16+
xFrameOptions: 'SAMEORIGIN',
17+
xPermittedCrossDomainPolicies: 'none',
18+
xXSSProtection: '0',
19+
}
20+
}
21+
}
22+
},
23+
security: {
24+
headers: {
25+
referrerPolicy: false,
26+
strictTransportSecurity: false,
27+
xContentTypeOptions: false,
28+
xDownloadOptions: false,
29+
xFrameOptions: false,
30+
xPermittedCrossDomainPolicies: false,
31+
xXSSProtection: false,
32+
contentSecurityPolicy: {
33+
'script-src': [
34+
"'self'",
35+
'https:',
36+
"'unsafe-inline'",
37+
"'strict-dynamic'"
38+
]
39+
}
40+
}
41+
}
42+
})
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"private": true,
3+
"name": "basic",
4+
"type": "module"
5+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<template>
2+
<div>basic</div>
3+
</template>
15.6 KB
Loading
15.6 KB
Loading

test/publicAssets.test.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { describe, it, expect } from 'vitest'
2+
import { fileURLToPath } from 'node:url'
3+
import { setup, fetch } from '@nuxt/test-utils'
4+
5+
describe('[nuxt-security] Public Assets', async () => {
6+
await setup({
7+
rootDir: fileURLToPath(new URL('./fixtures/publicAssets', import.meta.url)),
8+
})
9+
10+
it('does not set all-resources security headers when disabled in config', async () => {
11+
const { headers } = await fetch('/icon.png')
12+
expect(headers).toBeDefined()
13+
14+
// Security headers that are always set on all resources
15+
const rp = headers.get('referrer-policy')
16+
const sts = headers.get('strict-transport-security')
17+
const xcto = headers.get('x-content-type-options')
18+
const xdo = headers.get('x-download-options')
19+
const xfo = headers.get('x-frame-options')
20+
const xpcdp = headers.get('x-permitted-cross-domain-policies')
21+
const xxp = headers.get('x-xss-protection')
22+
23+
expect(rp).toBeNull()
24+
expect(sts).toBeNull()
25+
expect(xcto).toBeNull()
26+
expect(xdo).toBeNull()
27+
expect(xfo).toBeNull()
28+
expect(xpcdp).toBeNull()
29+
expect(xxp).toBeNull()
30+
})
31+
32+
it('sets security headers on routes when specified in routeRules', async () => {
33+
const { headers } = await fetch('/test')
34+
expect(headers).toBeDefined()
35+
36+
// Security headers that are always set on all resources
37+
const rp = headers.get('referrer-policy')
38+
const sts = headers.get('strict-transport-security')
39+
const xcto = headers.get('x-content-type-options')
40+
const xdo = headers.get('x-download-options')
41+
const xfo = headers.get('x-frame-options')
42+
const xpcdp = headers.get('x-permitted-cross-domain-policies')
43+
const xxp = headers.get('x-xss-protection')
44+
45+
expect(rp).toBe('no-referrer')
46+
expect(sts).toBe('max-age=15552000; includeSubDomains;')
47+
expect(xcto).toBe('nosniff')
48+
expect(xdo).toBe('noopen')
49+
expect(xfo).toBe('SAMEORIGIN')
50+
expect(xpcdp).toBe('none')
51+
expect(xxp).toBe('0')
52+
})
53+
})

0 commit comments

Comments
 (0)