summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErik Michelson2020-08-27 02:04:49 +0200
committerErik Michelson2020-08-27 02:04:49 +0200
commit824f910bfe39b8d789ca3edcfca44b66f603a81c (patch)
tree4038ca3553f9487eb1c476fa1d7b54355bd341b7
parent23d54b8b4b3a9587220c9211d2a92c22609a4de8 (diff)
Add config option for cookie SameSite policy
Signed-off-by: Erik Michelson <github@erik.michelson.eu>
-rw-r--r--app.js2
-rw-r--r--app.json4
-rw-r--r--config.json.example1
-rw-r--r--docs/configuration.md25
-rw-r--r--lib/config/default.js1
-rw-r--r--lib/config/environment.js1
-rw-r--r--lib/config/index.js5
-rw-r--r--lib/web/statusRouter.js3
-rw-r--r--public/js/index.js2
-rw-r--r--public/js/lib/common/constant.ejs2
-rw-r--r--public/js/lib/common/login.js4
-rw-r--r--public/js/lib/editor/index.js16
-rw-r--r--public/js/locale.js2
13 files changed, 42 insertions, 26 deletions
diff --git a/app.js b/app.js
index d102e816..236c77b9 100644
--- a/app.js
+++ b/app.js
@@ -147,7 +147,7 @@ app.use(session({
rolling: true, // reset maxAge on every response
cookie: {
maxAge: config.sessionLife,
- sameSite: 'lax',
+ sameSite: config.cookiePolicy, // be careful: setting a SameSite value of none without https breaks the editor
secure: config.useSSL || config.protocolUseSSL || false
},
store: sessionStore
diff --git a/app.json b/app.json
index f2a2b74c..4d68c0df 100644
--- a/app.json
+++ b/app.json
@@ -56,6 +56,10 @@
"description": "set to use ssl protocol for resources path (only applied when domain is set)",
"required": false
},
+ "CMD_COOKIE_POLICY": {
+ "description": "Set whether cookies should be sent cross-origin (SameSite value)",
+ "required": false
+ },
"CMD_URL_ADDPORT": {
"description": "set to add port on callback url (port 80 or 443 won't applied) (only applied when domain is set)",
"required": false
diff --git a/config.json.example b/config.json.example
index 0366c3b2..84ae53bd 100644
--- a/config.json.example
+++ b/config.json.example
@@ -35,6 +35,7 @@
"addDisqus": true,
"addGoogleAnalytics": true
},
+ "cookiePolicy": "strict",
"db": {
"username": "",
"password": "",
diff --git a/docs/configuration.md b/docs/configuration.md
index a6f63168..2b3ccad1 100644
--- a/docs/configuration.md
+++ b/docs/configuration.md
@@ -69,18 +69,19 @@ these are rarely used for various reasons.
| `urlAddPort` | `CMD_URL_ADDPORT` | **`false`** or `true` | set to add port on callback URL (ports `80` or `443` won't be applied) (only applied when domain is set) |
| `allowOrigin` | `CMD_ALLOW_ORIGIN` | **`['localhost']`**, `['codimd.org']`, `[localhost, codimd.org]` | domain name whitelist (use comma to separate) |
-## CSP and HSTS
-
-| config file | environment | **default** and example value | description |
-| ----------- | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `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) |
-| | `CMD_HSTS_ENABLE` | **`true`** or `false` | set to enable [HSTS](https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security) if HTTPS is also enabled (default is ` true`) |
-| | `CMD_HSTS_INCLUDE_SUBDOMAINS` | **`true`** or `false` | set to include subdomains in HSTS (default is `true`) |
-| | `CMD_HSTS_MAX_AGE` | **`31536000`**, `60 * 60 * 24 * 365` | max duration in seconds to tell clients to keep HSTS status (default is a year) |
-| | `CMD_HSTS_PRELOAD` | **`true`** or `false` | whether to allow preloading of the site's HSTS status (e.g. into browsers) |
-| `csp` | | `{"enable": true, "directives": {"scriptSrc": "trustworthy-scripts.example.com"}, "upgradeInsecureRequests": "auto", "addDefaults": true}` | Configures [Content Security Policy](https://helmetjs.github.io/docs/csp/). Directives are passed to Helmet - see [their documentation](https://helmetjs.github.io/docs/csp/) for more information on the format. Some defaults are added to the configured values so that the application doesn't break. To disable this behaviour, set `addDefaults` to `false`. Further, if `usecdn` is on, some 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`. |
-| | `CMD_CSP_ENABLE` | **`true`** or `false` | whether to enable Content Security Policy (directives cannot be configured with environment variables) |
-| | `CMD_CSP_REPORTURI` | **`undefined`**, `https://<someid>.report-uri.com/r/d/csp/enforce` | Allows to add a URL for CSP reports in case of violations |
+## Web security aspects
+
+| config file | environment | **default** and example value | description |
+| -------------- | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `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) |
+| | `CMD_HSTS_ENABLE` | **`true`** or `false` | set to enable [HSTS](https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security) if HTTPS is also enabled (default is ` true`) |
+| | `CMD_HSTS_INCLUDE_SUBDOMAINS` | **`true`** or `false` | set to include subdomains in HSTS (default is `true`) |
+| | `CMD_HSTS_MAX_AGE` | **`31536000`**, `60 * 60 * 24 * 365` | max duration in seconds to tell clients to keep HSTS status (default is a year) |
+| | `CMD_HSTS_PRELOAD` | **`true`** or `false` | whether to allow preloading of the site's HSTS status (e.g. into browsers) |
+| `csp` | | `{"enable": true, "directives": {"scriptSrc": "trustworthy-scripts.example.com"}, "upgradeInsecureRequests": "auto", "addDefaults": true}` | Configures [Content Security Policy](https://helmetjs.github.io/docs/csp/). Directives are passed to Helmet - see [their documentation](https://helmetjs.github.io/docs/csp/) for more information on the format. Some defaults are added to the configured values so that the application doesn't break. To disable this behaviour, set `addDefaults` to `false`. Further, if `usecdn` is on, some 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`. |
+| | `CMD_CSP_ENABLE` | **`true`** or `false` | whether to enable Content Security Policy (directives cannot be configured with environment variables) |
+| | `CMD_CSP_REPORTURI` | **`undefined`**, `https://<someid>.report-uri.com/r/d/csp/enforce` | Allows to add a URL for CSP reports in case of violations |
+| `cookiePolicy` | `CMD_COOKIE_POLICY` | **`strict`**, `lax` or `none` | Set a SameSite policy whether cookies are send from cross-origin. Be careful: setting a SameSite value of none without https breaks the editor |
## Privacy and External Requests
diff --git a/lib/config/default.js b/lib/config/default.js
index 9284882a..3d1a1367 100644
--- a/lib/config/default.js
+++ b/lib/config/default.js
@@ -27,6 +27,7 @@ module.exports = {
upgradeInsecureRequests: 'auto',
reportURI: undefined
},
+ cookiePolicy: 'strict',
protocolUseSSL: false,
useCDN: false,
allowAnonymous: true,
diff --git a/lib/config/environment.js b/lib/config/environment.js
index 2d76286f..cf9fb5a1 100644
--- a/lib/config/environment.js
+++ b/lib/config/environment.js
@@ -22,6 +22,7 @@ module.exports = {
enable: toBooleanConfig(process.env.CMD_CSP_ENABLE),
reportURI: process.env.CMD_CSP_REPORTURI
},
+ cookiePolicy: process.env.CMD_COOKIE_POLICY,
protocolUseSSL: toBooleanConfig(process.env.CMD_PROTOCOL_USESSL),
allowOrigin: toArrayConfig(process.env.CMD_ALLOW_ORIGIN),
useCDN: toBooleanConfig(process.env.CMD_USECDN),
diff --git a/lib/config/index.js b/lib/config/index.js
index ee4817b3..020dee13 100644
--- a/lib/config/index.js
+++ b/lib/config/index.js
@@ -51,6 +51,11 @@ if (['debug', 'verbose', 'info', 'warn', 'error'].includes(config.loglevel)) {
logger.error('Selected loglevel %s doesn\'t exist, using default level \'debug\'. Available options: debug, verbose, info, warn, error', config.loglevel)
}
+if (!['strict', 'lax', 'none'].includes(config.cookiePolicy)) {
+ logger.error('Cookie SameSite policy %s does not exist. Falling back to strict. Available values are: strict, lax, none.', config.cookiePolicy)
+ config.cookiePolicy = 'strict'
+}
+
// load LDAP CA
if (config.ldap.tlsca) {
let ca = config.ldap.tlsca.split(',')
diff --git a/lib/web/statusRouter.js b/lib/web/statusRouter.js
index 025aafd4..febe2df3 100644
--- a/lib/web/statusRouter.js
+++ b/lib/web/statusRouter.js
@@ -97,7 +97,8 @@ statusRouter.get('/config', function (req, res) {
version: config.fullversion,
DROPBOX_APP_KEY: config.dropbox.appKey,
allowedUploadMimeTypes: config.allowedUploadMimeTypes,
- linkifyHeaderStyle: config.linkifyHeaderStyle
+ linkifyHeaderStyle: config.linkifyHeaderStyle,
+ cookiePolicy: config.cookiePolicy
}
res.set({
'Cache-Control': 'private', // only cache by client
diff --git a/public/js/index.js b/public/js/index.js
index ad20ffff..36f396fa 100644
--- a/public/js/index.js
+++ b/public/js/index.js
@@ -1597,7 +1597,7 @@ function toggleNightMode () {
} else {
Cookies.set('nightMode', !isActive, {
expires: 365,
- sameSite: 'strict'
+ sameSite: window.cookiePolicy
})
}
}
diff --git a/public/js/lib/common/constant.ejs b/public/js/lib/common/constant.ejs
index 114a9077..2a32c333 100644
--- a/public/js/lib/common/constant.ejs
+++ b/public/js/lib/common/constant.ejs
@@ -8,3 +8,5 @@ window.allowedUploadMimeTypes = <%- JSON.stringify(allowedUploadMimeTypes) %>
window.linkifyHeaderStyle = '<%- linkifyHeaderStyle %>'
window.DROPBOX_APP_KEY = '<%- DROPBOX_APP_KEY %>'
+
+window.cookiePolicy = '<%- cookiePolicy %>'
diff --git a/public/js/lib/common/login.js b/public/js/lib/common/login.js
index 931c115f..3f7a3e4d 100644
--- a/public/js/lib/common/login.js
+++ b/public/js/lib/common/login.js
@@ -20,12 +20,12 @@ export function resetCheckAuth () {
export function setLoginState (bool, id) {
Cookies.set('loginstate', bool, {
expires: 365,
- sameSite: 'strict'
+ sameSite: window.cookiePolicy
})
if (id) {
Cookies.set('userid', id, {
expires: 365,
- sameSite: 'strict'
+ sameSite: window.cookiePolicy
})
} else {
Cookies.remove('userid')
diff --git a/public/js/lib/editor/index.js b/public/js/lib/editor/index.js
index 07ef58a1..d86ebf3c 100644
--- a/public/js/lib/editor/index.js
+++ b/public/js/lib/editor/index.js
@@ -304,13 +304,13 @@ export default class Editor {
if (this.editor.getOption('indentWithTabs')) {
Cookies.set('indent_type', 'tab', {
expires: 365,
- sameSite: 'strict'
+ sameSite: window.cookiePolicy
})
type.text('Tab Size:')
} else {
Cookies.set('indent_type', 'space', {
expires: 365,
- sameSite: 'strict'
+ sameSite: window.cookiePolicy
})
type.text('Spaces:')
}
@@ -322,12 +322,12 @@ export default class Editor {
if (this.editor.getOption('indentWithTabs')) {
Cookies.set('tab_size', unit, {
expires: 365,
- sameSite: 'strict'
+ sameSite: window.cookiePolicy
})
} else {
Cookies.set('space_units', unit, {
expires: 365,
- sameSite: 'strict'
+ sameSite: window.cookiePolicy
})
}
widthLabel.text(unit)
@@ -396,7 +396,7 @@ export default class Editor {
var keymap = this.editor.getOption('keyMap')
Cookies.set('keymap', keymap, {
expires: 365,
- sameSite: 'strict'
+ sameSite: window.cookiePolicy
})
label.text(keymap)
this.restoreOverrideEditorKeymap()
@@ -445,7 +445,7 @@ export default class Editor {
this.editor.setOption('theme', theme)
Cookies.set('theme', theme, {
expires: 365,
- sameSite: 'strict'
+ sameSite: window.cookiePolicy
})
checkTheme()
@@ -491,7 +491,7 @@ export default class Editor {
}
Cookies.set('spellcheck', mode === 'spell-checker', {
expires: 365,
- sameSite: 'strict'
+ sameSite: window.cookiePolicy
})
checkSpellcheck()
@@ -537,7 +537,7 @@ export default class Editor {
if (overrideBrowserKeymap.is(':checked')) {
Cookies.set('preferences-override-browser-keymap', true, {
expires: 365,
- sameSite: 'strict'
+ sameSite: window.cookiePolicy
})
this.restoreOverrideEditorKeymap()
} else {
diff --git a/public/js/locale.js b/public/js/locale.js
index aca35b98..8baa77fc 100644
--- a/public/js/locale.js
+++ b/public/js/locale.js
@@ -31,7 +31,7 @@ if (localeSelector.length > 0) {
localeSelector.change(function () {
Cookies.set('locale', $(this).val(), {
expires: 365,
- sameSite: 'strict'
+ sameSite: window.cookiePolicy
})
window.location.reload()
})