summaryrefslogtreecommitdiff
path: root/test/csp.js
blob: 8cf24b9a7bfbab150df3c5d7b6cdb7eb515e490f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/* eslint-env node, mocha */
'use strict'

const assert = require('assert')
const crypto = require('crypto')
const fs = require('fs')
const path = require('path')
const mock = require('mock-require')

describe('Content security policies', function () {
  let defaultConfig, csp

  before(function () {
    csp = require('../lib/csp')
  })

  beforeEach(function () {
    // Reset config to make sure we don't influence other tests
    defaultConfig = {
      csp: {
        enable: true,
        directives: {
        },
        addDefaults: true,
        addDisqus: true,
        addGoogleAnalytics: true,
        upgradeInsecureRequests: 'auto',
        reportURI: undefined
      },
      useCDN: true
    }
  })

  afterEach(function () {
    mock.stop('../lib/config')
    csp = mock.reRequire('../lib/csp')
  })

  after(function () {
    mock.stopAll()
    csp = mock.reRequire('../lib/csp')
  })

  // beginnging Tests
  it('Disable CDN', function () {
    let testconfig = defaultConfig
    testconfig.useCDN = false
    mock('../lib/config', testconfig)
    csp = mock.reRequire('../lib/csp')

    assert(!csp.computeDirectives().scriptSrc.includes('https://cdnjs.cloudflare.com'))
    assert(!csp.computeDirectives().scriptSrc.includes('https://cdn.mathjax.org'))
    assert(!csp.computeDirectives().styleSrc.includes('https://cdnjs.cloudflare.com'))
    assert(!csp.computeDirectives().styleSrc.includes('https://fonts.googleapis.com'))
    assert(!csp.computeDirectives().fontSrc.includes('https://cdnjs.cloudflare.com'))
    assert(!csp.computeDirectives().fontSrc.includes('https://fonts.gstatic.com'))
  })

  it('Disable Google Analytics', function () {
    let testconfig = defaultConfig
    testconfig.csp.addGoogleAnalytics = false
    mock('../lib/config', testconfig)
    csp = mock.reRequire('../lib/csp')

    assert(!csp.computeDirectives().scriptSrc.includes('https://www.google-analytics.com'))
  })

  it('Disable Disqus', function () {
    let testconfig = defaultConfig
    testconfig.csp.addDisqus = false
    mock('../lib/config', testconfig)
    csp = mock.reRequire('../lib/csp')

    assert(!csp.computeDirectives().scriptSrc.includes('https://disqus.com'))
    assert(!csp.computeDirectives().scriptSrc.includes('https://*.disqus.com'))
    assert(!csp.computeDirectives().scriptSrc.includes('https://*.disquscdn.com'))
    assert(!csp.computeDirectives().styleSrc.includes('https://*.disquscdn.com'))
    assert(!csp.computeDirectives().fontSrc.includes('https://*.disquscdn.com'))
  })

  it('Set ReportURI', function () {
    let testconfig = defaultConfig
    testconfig.csp.reportURI = 'https://example.com/reportURI'
    mock('../lib/config', testconfig)
    csp = mock.reRequire('../lib/csp')

    assert.strictEqual(csp.computeDirectives().reportUri, 'https://example.com/reportURI')
  })

  it('Set own directives', function () {
    let testconfig = defaultConfig
    mock('../lib/config', defaultConfig)
    csp = mock.reRequire('../lib/csp')
    const unextendedCSP = csp.computeDirectives()
    testconfig.csp.directives = {
      defaultSrc: ['https://default.example.com'],
      scriptSrc: ['https://script.example.com'],
      imgSrc: ['https://img.example.com'],
      styleSrc: ['https://style.example.com'],
      fontSrc: ['https://font.example.com'],
      objectSrc: ['https://object.example.com'],
      mediaSrc: ['https://media.example.com'],
      childSrc: ['https://child.example.com'],
      connectSrc: ['https://connect.example.com']
    }
    mock('../lib/config', testconfig)
    csp = mock.reRequire('../lib/csp')

    const variations = ['default', 'script', 'img', 'style', 'font', 'object', 'media', 'child', 'connect']

    for (let i = 0; i < variations.length; i++) {
      assert.strictEqual(csp.computeDirectives()[variations[i] + 'Src'].toString(), ['https://' + variations[i] + '.example.com'].concat(unextendedCSP[variations[i] + 'Src']).toString())
    }
  })

  /*
   * This test reminds us to update the CSP hash for the speaker notes
   */
  it('Unchanged hash for reveal.js speaker notes plugin', function () {
    const hash = crypto.createHash('sha1')
    hash.update(fs.readFileSync(path.resolve(__dirname, '../node_modules/reveal.js/plugin/notes/notes.html'), 'utf8'), 'utf8')
    assert.strictEqual(hash.digest('hex'), 'd5d872ae49b5db27f638b152e6e528837204d380')
  })
})