From 2733a8dd0d2c8a54e291b93abf697b0a86c83a04 Mon Sep 17 00:00:00 2001 From: 1000TurquoisePogs Date: Tue, 6 Jul 2021 10:36:37 -0400 Subject: [PATCH] Adding ability to set a nonce and alter an html template to use it Signed-off-by: 1000TurquoisePogs --- lib/webapp.js | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/lib/webapp.js b/lib/webapp.js index fbbf404a..33c0f291 100644 --- a/lib/webapp.js +++ b/lib/webapp.js @@ -199,6 +199,10 @@ function getPresetHeader(name, preset, req) { return `default-src 'self' ${req.hostname};`; } else if (preset == 'frame-strict') { return `frame-src 'self' ${req.hostname};`; + } else if (preset == 'script-nonce') { + let nonce=crypto.randomBytes(16).toString('hex'); + req.nonce=nonce; + return `script-src 'nonce-${nonce}' 'strict-dynamic' 'unsafe-eval'`; } break; } @@ -1425,7 +1429,9 @@ WebApp.prototype = { res.redirect(rootPage); }); } - this.expressApp.use(rootPage, express.static(webdir)); + if (fs.existsSync(webdir)) { + this.expressApp.use(rootPage, express.static(webdir)); + } }, installCommonMiddleware() { @@ -1840,9 +1846,28 @@ WebApp.prototype = { } middleware.push(commonMiddleware.customHeaderInjection(headersArray)); } - middleware.push(expressStaticGzip(path.join(plugin.location, '/web'), + let webMiddleware = middleware.slice(); + webMiddleware.push(expressStaticGzip(path.join(plugin.location, '/web'), {enableBrotli: true, orderPreference: ['br', 'gzip']})); - this.pluginRouter.use(url, middleware); + + //Used to replace nonce template with server value + if (fs.existsSync(path.join(plugin.location, 'web', 'index.html')) && plugin.webContent.headers) { + let indexMiddleware = middleware.slice(); + indexMiddleware.push((req,res,next)=>{ + console.log(`nonce=${req.nonce} and path=${req.path}`); + if (req.nonce && (req.path == '/' || req.path == '/index.html')) { + fs.readFile(path.join(plugin.location, 'web', 'index.html'), {encoding: 'utf8'}, (err, data)=> { + res.status(200).send(data.replace('nonce="{{nonce}}', 'nonce="'+req.nonce)); + }); + } else { next() } + }); + indexMiddleware.push(expressStaticGzip(path.join(plugin.location, '/web'), + {enableBrotli: true, orderPreference: ['br', 'gzip']})); + this.pluginRouter.use(url, indexMiddleware); + //but if no template candidate, skip that for performance. + } else { + this.pluginRouter.use(url, webMiddleware); + } } if (plugin.pluginType === "library") { if (plugin.libraryVersion) {