Skip to content

Commit

Permalink
chore: add nonce test for inline styling tags
Browse files Browse the repository at this point in the history
  • Loading branch information
trijpstra-fourlights committed Jul 17, 2023
1 parent a2fd154 commit 2d4fefa
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 27 deletions.
10 changes: 10 additions & 0 deletions test/fixtures/nonce/app.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,13 @@
<NuxtPage />
</div>
</template>

<script lang="ts" setup>
useHead({
script: [
{ src: '/api/generated-script' }
]
// workaround for double loads in ssr when using nonce
// see: https://github.com/unjs/unhead/issues/136
}, { mode: 'server' })
</script>
14 changes: 0 additions & 14 deletions test/fixtures/nonce/nuxt.config.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,6 @@
import MyModule from '../../../src/module'

export default defineNuxtConfig({
app: {
// workaround for double loads in ssr when using nonce
// see: https://github.com/unjs/unhead/issues/136
head: () => (process.server
? {
script: [
{ src: '/loader.js' },
{ src: '/api/generated-script' },
{ innerHTML: 'var inlineLiteral = \'<script>console.log("example")</script>\'' }
]
}
: {})
},

modules: [
MyModule
],
Expand Down
13 changes: 6 additions & 7 deletions test/fixtures/nonce/pages/use-head.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@
</template>

<script lang="ts" setup>
const nonce = useNonce()
useHead({
script: () => ({
key: 'loader',
src: 'loader.js',
nonce
})
script: () => {
return {
key: 'loader',
src: 'loader.js'
}
}
}, { mode: 'server' }) // workaround double load on ssr, see https://github.com/unjs/unhead/issues/136
</script>
13 changes: 13 additions & 0 deletions test/fixtures/nonce/pages/with-inline-script.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<template>
<div>
test
</div>
</template>

<script setup>
useHead({
script: [
{ innerHTML: "var inlineLiteral = '\x3Cscript>console.log(\"example\")'" }
]
}, { mode: 'server' })
</script>
9 changes: 9 additions & 0 deletions test/fixtures/nonce/pages/with-styling.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<template>
<div>test</div>
</template>

<style>
div {
color: red;
}
</style>
27 changes: 21 additions & 6 deletions test/nonce.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ describe('[nuxt-security] Nonce', async () => {
rootDir: fileURLToPath(new URL('./fixtures/nonce', import.meta.url))
})

const expectedNonceElements = 9 // 3 head scripts + 3 styles + 3 script attributes
const expectedNonceElements = 7 // 1 from app.vue/useHead, 6 for nuxt

it('injects `nonce` attribute in response', async () => {
const res = await fetch('/')

const cspHeaderValue = res.headers.get('content-security-policy')
const nonce = cspHeaderValue?.match(/'nonce-(.*?)'/)[1]
const nonce = cspHeaderValue?.match(/'nonce-(.*?)'/)![1]

const text = await res.text()
const elementsWithNonce = text.match(new RegExp(`nonce="${nonce}"`, 'g'))?.length ?? 0
Expand Down Expand Up @@ -43,15 +43,15 @@ describe('[nuxt-security] Nonce', async () => {
const res = await fetch('/use-head')

const cspHeaderValue = res.headers.get('content-security-policy')
const nonce = cspHeaderValue?.match(/'nonce-(.*?)'/)[1]
const nonce = cspHeaderValue!.match(/'nonce-(.*?)'/)![1]

const text = await res.text()
const elementsWithNonce = text.match(new RegExp(`nonce="${nonce}"`, 'g'))?.length ?? 0

expect(res).toBeDefined()
expect(res).toBeTruthy()
expect(nonce).toBeDefined()
expect(elementsWithNonce).toBe(11)
expect(elementsWithNonce).toBe(expectedNonceElements + 1) // 1 extra for loader.js in useHead
})

it('removes the nonce from the CSP header when nonce is disabled', async () => {
Expand All @@ -65,11 +65,26 @@ describe('[nuxt-security] Nonce', async () => {
})

it('does not add nonce to literal strings', async () => {
const res = await fetch('/')
const res = await fetch('/with-inline-script')

const text = await res.text()
const untouchedLiteral = text.includes('var inlineLiteral = \'<script>console.log("example")</script>\'')
const untouchedLiteral = text.includes('var inlineLiteral = \'<script>console.log("example")\'')

expect(untouchedLiteral).toBe(true)
})

it('injects `nonce` attribute in style tags', async () => {
const res = await fetch('/with-styling')

const cspHeaderValue = res.headers.get('content-security-policy')
const nonce = cspHeaderValue?.match(/'nonce-(.*?)'/)![1]

const text = await res.text()
const elementsWithNonce = text.match(new RegExp(`nonce="${nonce}"`, 'g'))?.length ?? 0

expect(res).toBeDefined()
expect(res).toBeTruthy()
expect(nonce).toBeDefined()
expect(elementsWithNonce).toBe(expectedNonceElements + 1) // one extra for the style tag
})
})

0 comments on commit 2d4fefa

Please sign in to comment.