summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLiterallie2017-10-20 12:31:16 +0200
committerLiterallie2017-10-22 00:03:46 +0200
commit91101c856c3efac53e8a4db4cc537b77370aa7df (patch)
tree5bc25f9d094dc5b3c85248711c37619d3e62abdd
parent5b83deb043296c23ff912a2472703c1f7faddb4b (diff)
Change CSP config format to be more intuitive
-rw-r--r--README.md2
-rw-r--r--app.js40
-rw-r--r--config.json.example7
-rw-r--r--lib/config/default.js10
-rw-r--r--lib/config/environment.js3
5 files changed, 48 insertions, 14 deletions
diff --git a/README.md b/README.md
index 6e2e710d..d71eb1c5 100644
--- a/README.md
+++ b/README.md
@@ -158,6 +158,7 @@ Environment variables (will overwrite other server configs)
| HMD_HSTS_INCLUDE_SUBDOMAINS | `true` | set to include subdomains in HSTS (default is `true`) |
| HMD_HSTS_MAX_AGE | `31536000` | max duration in seconds to tell clients to keep HSTS status (default is a year) |
| HMD_HSTS_PRELOAD | `true` | whether to allow preloading of the site's HSTS status (e.g. into browsers) |
+| HMD_CSP_ENABLE | `true` | whether to enable Content Security Policy (directives cannot be configured with environment variables) |
Application settings `config.json`
---
@@ -171,6 +172,7 @@ Application settings `config.json`
| alloworigin | `['localhost']` | domain name whitelist |
| usessl | `true` or `false` | set to use ssl server (if true will auto turn on `protocolusessl`) |
| hsts | `{"enable": "true", "maxAgeSeconds": "31536000", "includeSubdomains": "true", "preload": "true"}` | [HSTS](https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security) options to use with HTTPS (default is the example value, max age is a year) |
+| csp | `{"enable": "true", "directives": {"scriptSrc": "trustwodthy-scripts.example.com"}, "upgradeInsecureRequests": "auto", "addDefaults": "true"}` | Configures [Content Security Policy](https://helmetjs.github.io/docs/csp/). Directives are directly passed to Helmet, so [their format](https://helmetjs.github.io/docs/csp/) applies. Further, some defaults are added so that the application doesn't break. To disable adding these defaults, set `addDefaults` to `false`. If `usecdn` is on, default CDN locations are allowed too. By default (`auto`), insecure (HTTP) requests are upgraded to HTTPS via CSP if `usessl` is on. To change this behaviour, set `upgradeInsecureRequests` to either `true` or `false`. |
| protocolusessl | `true` or `false` | set to use ssl protocol for resources path (only applied when domain is set) |
| urladdport | `true` or `false` | set to add port on callback url (port 80 or 443 won't applied) (only applied when domain is set) |
| usecdn | `true` or `false` | set to use CDN resources or not (default is `true`) |
diff --git a/app.js b/app.js
index 15c9e61e..01ecc84c 100644
--- a/app.js
+++ b/app.js
@@ -125,7 +125,28 @@ function getCspWebSocketUrl (req, res) {
return (req.protocol === 'http' ? 'ws:' : 'wss:') + config.serverurl.replace(/https?:/, "")
}
+function mergeWithDefaults(configured, defaultDirective, cdnDirective) {
+ var directive = [].concat(configured)
+ if (config.csp.addDefaults && defaultDirective) {
+ directive = directive.concat(defaultDirective)
+ }
+ if (config.usecdn && cdnDirective) {
+ directive = directive.concat(cdnDirective)
+ }
+ return directive
+}
+
if (config.csp.enable) {
+ var defaultDirectives = {
+ defaultSrc: ['\'self\''],
+ scriptSrc: ['\'self\'', 'vimeo.com', 'https://gist.github.com', 'www.slideshare.net', 'https://query.yahooapis.com', 'https://*.disqus.com', '\'unsafe-eval\''], // TODO: Remove unsafe-eval - webpack script-loader issues
+ imgSrc: ['*'],
+ styleSrc: ['\'self\'', '\'unsafe-inline\'', 'https://assets-cdn.github.com'], // unsafe-inline is required for some libs, plus used in views
+ fontSrc: ['\'self\'', 'https://public.slidesharecdn.com'],
+ objectSrc: ['*'], // Chrome PDF viewer treats PDFs as objects :/
+ childSrc: ['*'],
+ connectSrc: ['\'self\'', 'https://links.services.disqus.com', 'wss://realtime.services.disqus.com']
+ };
var cdnDirectives = {
scriptSrc: ['https://cdnjs.cloudflare.com', 'https://cdn.mathjax.org'],
styleSrc: ['https://cdnjs.cloudflare.com', 'https://fonts.googleapis.com'],
@@ -134,11 +155,20 @@ if (config.csp.enable) {
var directives = {}
for (var propertyName in config.csp.directives) {
if (config.csp.directives.hasOwnProperty(propertyName)) {
- var directive = [].concat(config.csp.directives[propertyName])
- if (config.usecdn && !!cdnDirectives[propertyName]) {
- directive = directive.concat(cdnDirectives[propertyName])
- }
- directives[propertyName] = directive
+ directives[propertyName] = mergeWithDefaults(
+ config.csp.directives[propertyName],
+ defaultDirectives[propertyName],
+ cdnDirectives[propertyName]
+ )
+ }
+ }
+ for (var propertyName in defaultDirectives) {
+ if (!directives[propertyName]) {
+ directives[propertyName] = mergeWithDefaults(
+ [],
+ defaultDirectives[propertyName],
+ cdnDirectives[propertyName]
+ )
}
}
directives.scriptSrc.push(getCspNonce)
diff --git a/config.json.example b/config.json.example
index e2d774c7..7e4394b0 100644
--- a/config.json.example
+++ b/config.json.example
@@ -22,6 +22,13 @@
"includeSubdomains": "true",
"preload": "true"
},
+ csp: {
+ "enable": "true",
+ "directives": {
+ },
+ "upgradeInsecureRequests": "auto"
+ "addDefaults": "true"
+ },
"db": {
"username": "",
"password": "",
diff --git a/lib/config/default.js b/lib/config/default.js
index 0b6ca26a..cfde9ae9 100644
--- a/lib/config/default.js
+++ b/lib/config/default.js
@@ -15,17 +15,9 @@ module.exports = {
},
csp: {
enable: true,
- reportUri: '',
directives: {
- defaultSrc: ["'self'"],
- scriptSrc: ["'self'", "'unsafe-eval'", "vimeo.com", "https://gist.github.com", "www.slideshare.net", "https://query.yahooapis.com", "https://*.disqus.com"],
- imgSrc: ["*"],
- styleSrc: ["'self'", "'unsafe-inline'", "https://assets-cdn.github.com"],
- fontSrc: ["'self'", "https://public.slidesharecdn.com"],
- objectSrc: ["*"],
- childSrc: ["*"],
- connectSrc: ["'self'", "https://links.services.disqus.com", "wss://realtime.services.disqus.com"]
},
+ addDefaults: true,
upgradeInsecureRequests: 'auto'
},
protocolusessl: false,
diff --git a/lib/config/environment.js b/lib/config/environment.js
index 40b7e09f..fa9698f6 100644
--- a/lib/config/environment.js
+++ b/lib/config/environment.js
@@ -14,6 +14,9 @@ module.exports = {
includeSubdomains: toBooleanConfig(process.env.HMD_HSTS_INCLUDE_SUBDOMAINS),
preload: toBooleanConfig(process.env.HMD_HSTS_PRELOAD)
},
+ csp: {
+ enable: toBooleanConfig(process.env.HMD_CSP_ENABLE)
+ },
protocolusessl: toBooleanConfig(process.env.HMD_PROTOCOL_USESSL),
alloworigin: process.env.HMD_ALLOW_ORIGIN ? process.env.HMD_ALLOW_ORIGIN.split(',') : undefined,
usecdn: toBooleanConfig(process.env.HMD_USECDN),