diff --git a/client.csp.demo/app.js b/client.csp.demo/app.js index 1be358d..8172e64 100644 --- a/client.csp.demo/app.js +++ b/client.csp.demo/app.js @@ -3,6 +3,7 @@ const nunjucks = require('nunjucks') const cookieParser = require('cookie-parser') const exerciseRoutes = require('./routes/exercise') const resHeaders = require('./middleware/responseHeaders') +const generateNonce = require('./middleware/generateNonce') const app = express() const jucksEnv = new nunjucks.Environment(new nunjucks.FileSystemLoader('client.csp.demo/views')) @@ -24,7 +25,7 @@ global.cspDirectives = { 'default-src': `'self'`, 'use-default-src': 'on' } const globalCsp = (req, res, next) => { if(global.csp.trim().length > 0) { - res.set('Content-Security-Policy', global.csp) + res.set('Content-Security-Policy', global.csp.replace(/\$nonce/g, res.nonce)) } next() } @@ -40,8 +41,8 @@ const constructCSP = ((supportedDirectives)=>{ } })(supportedDirectives) -app.get('/', globalCsp, (req, res) => res.render('index')) -app.post('/', express.urlencoded(), globalCsp, (req, res) => res.render('index', { payload: req.body.unsafeReflection })) +app.get('/', generateNonce, globalCsp, (req, res) => res.render('index', { nonce: res.nonce })) +app.post('/', express.urlencoded(), generateNonce, globalCsp, (req, res) => res.render('index', { payload: req.body.unsafeReflection, nonce: res.nonce })) app.get('/set-csp', (req, res) => res.render('set-csp', { msg: req.query.msg, allDirectives: supportedDirectives, currDirectives: cspDirectives })) app.post('/set-csp', express.urlencoded(), (req, res) => { csp = constructCSP(req.body) diff --git a/client.csp.demo/middleware/generateNonce.js b/client.csp.demo/middleware/generateNonce.js new file mode 100644 index 0000000..3eec34b --- /dev/null +++ b/client.csp.demo/middleware/generateNonce.js @@ -0,0 +1,9 @@ +const crypto = require('crypto') + +const generateNonce = (_, res, next) => { + let nonce = crypto.randomBytes(16).toString('hex'); + res.nonce = nonce; + next() +} + +module.exports = generateNonce; \ No newline at end of file diff --git a/client.csp.demo/routes/exercise.js b/client.csp.demo/routes/exercise.js index 8a56481..a457190 100644 --- a/client.csp.demo/routes/exercise.js +++ b/client.csp.demo/routes/exercise.js @@ -27,12 +27,12 @@ router.get('/2', (req, res) => { router.post('/2', express.urlencoded(), (req, res) => { if(req.body.email) { if(/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(req.body.email)) { - res.render(`ex2`, {cspIsSet: req.exSetPolicy, isPost: true, isSuccess: false, emailAddr: '', message: 'If the supplied email matches a valid user in this app, an email will be sent with reset instructions.'}); + res.render(`ex2`, {cspIsSet: req.exSetPolicy, nonce: res.nonce, isPost: true, isSuccess: false, emailAddr: '', message: 'If the supplied email matches a valid user in this app, an email will be sent with reset instructions.'}); } else { - res.render(`ex2`, {cspIsSet: req.exSetPolicy, isPost: true, isSuccess: false, emailAddr: req.body.email, message: 'The supplied email address appeared to be improperly formatted.' }); + res.render(`ex2`, {cspIsSet: req.exSetPolicy, nonce: res.nonce, isPost: true, isSuccess: false, emailAddr: req.body.email, message: 'The supplied email address appeared to be improperly formatted.' }); } } else { - res.render(`ex2`, {cspIsSet: req.exSetPolicy, isPost: true, isSuccess: false, emailAddr: ''}); + res.render(`ex2`, {cspIsSet: req.exSetPolicy, nonce: res.nonce, isPost: true, isSuccess: false, emailAddr: ''}); } }); diff --git a/client.csp.demo/views/ex2.njk b/client.csp.demo/views/ex2.njk index 31a5fc3..962f91a 100644 --- a/client.csp.demo/views/ex2.njk +++ b/client.csp.demo/views/ex2.njk @@ -44,6 +44,6 @@ - - + + {% endblock %} \ No newline at end of file diff --git a/client.csp.demo/views/index.njk b/client.csp.demo/views/index.njk index 19112a0..5c17f57 100644 --- a/client.csp.demo/views/index.njk +++ b/client.csp.demo/views/index.njk @@ -42,5 +42,5 @@ - + {% endblock %} \ No newline at end of file diff --git a/client.csp.demo/views/set-csp.njk b/client.csp.demo/views/set-csp.njk index d4194cc..8df8719 100644 --- a/client.csp.demo/views/set-csp.njk +++ b/client.csp.demo/views/set-csp.njk @@ -34,6 +34,7 @@
{{ msg }}
+

Using $nonce will replace value with the random nonce generated for the request.