From 294a444603ada0804755a9ccb39a8989623be5d2 Mon Sep 17 00:00:00 2001 From: ansuz Date: Thu, 27 Feb 2020 13:09:12 -0500 Subject: [PATCH 01/27] WIP removing defaults from the example config file --- config/config.example.js | 56 ++++------------------------------ lib/defaults.js | 65 ++++++++++++++++++++++++++++++++++++++++ lib/load-config.js | 2 +- 3 files changed, 71 insertions(+), 52 deletions(-) create mode 100644 lib/defaults.js diff --git a/config/config.example.js b/config/config.example.js index 90e96a66a..e2bcea5bc 100644 --- a/config/config.example.js +++ b/config/config.example.js @@ -16,37 +16,7 @@ var _domain = 'http://localhost:3000/'; // requiring admins to preserve it is unnecessarily confusing var domain = ' ' + _domain; -// Content-Security-Policy -var baseCSP = [ - "default-src 'none'", - "style-src 'unsafe-inline' 'self' " + domain, - "font-src 'self' data:" + domain, - - /* child-src is used to restrict iframes to a set of allowed domains. - * connect-src is used to restrict what domains can connect to the websocket. - * - * it is recommended that you configure these fields to match the - * domain which will serve your CryptPad instance. - */ - "child-src blob: *", - // IE/Edge - "frame-src blob: *", - - /* this allows connections over secure or insecure websockets - if you are deploying to production, you'll probably want to remove - the ws://* directive, and change '*' to your domain - */ - "connect-src 'self' ws: wss: blob:" + domain, - - // data: is used by codemirror - "img-src 'self' data: blob:" + domain, - "media-src * blob:", - - // for accounts.cryptpad.fr authentication and cross-domain iframe sandbox - "frame-ancestors *", - "" -]; - +var Default = require("../lib/defaults"); module.exports = { /* ===================== @@ -113,34 +83,18 @@ module.exports = { * These settings may vary widely depending on your needs * Examples are provided below */ - httpHeaders: { - "X-XSS-Protection": "1; mode=block", - "X-Content-Type-Options": "nosniff", - "Access-Control-Allow-Origin": "*" - }, + httpHeaders: Default.httpHeaders(), - contentSecurity: baseCSP.join('; ') + - "script-src 'self'" + domain, + contentSecurity: Default.contentSecurity(domain), // CKEditor and OnlyOffice require significantly more lax content security policy in order to function. - padContentSecurity: baseCSP.join('; ') + - "script-src 'self' 'unsafe-eval' 'unsafe-inline'" + domain, + padContentSecurity: Default.padContentSecurity(domain), /* Main pages * add exceptions to the router so that we can access /privacy.html * and other odd pages */ - mainPages: [ - 'index', - 'privacy', - 'terms', - 'about', - 'contact', - 'what-is-cryptpad', - 'features', - 'faq', - 'maintenance' - ], + mainPages: Default.mainPages(), /* ===================== * Subscriptions diff --git a/lib/defaults.js b/lib/defaults.js new file mode 100644 index 000000000..f5d87b20b --- /dev/null +++ b/lib/defaults.js @@ -0,0 +1,65 @@ +var Default = module.exports; + +Default.commonCSP = function (domain) { + // Content-Security-Policy + return [ + "default-src 'none'", + "style-src 'unsafe-inline' 'self' " + domain, + "font-src 'self' data:" + domain, + + /* child-src is used to restrict iframes to a set of allowed domains. + * connect-src is used to restrict what domains can connect to the websocket. + * + * it is recommended that you configure these fields to match the + * domain which will serve your CryptPad instance. + */ + "child-src blob: *", + // IE/Edge + "frame-src blob: *", + + /* this allows connections over secure or insecure websockets + if you are deploying to production, you'll probably want to remove + the ws://* directive, and change '*' to your domain + */ + "connect-src 'self' ws: wss: blob:" + domain, + + // data: is used by codemirror + "img-src 'self' data: blob:" + domain, + "media-src * blob:", + + // for accounts.cryptpad.fr authentication and cross-domain iframe sandbox + "frame-ancestors *", + "" + ]; +}; + +Default.contentSecurity = function (domain) { + return Default.commonCSP(domain).join('; ') + "script-src 'self'" + domain; +}; + +Default.padContentSecurity = function (domain) { + return Default.commonCSP(domain).join('; ') + "script-src 'self' 'unsafe-eval' 'unsafe-inline'" + domain; +}; + +Default.httpHeaders = function () { + return { + "X-XSS-Protection": "1; mode=block", + "X-Content-Type-Options": "nosniff", + "Access-Control-Allow-Origin": "*" + }; +}; + +Default.mainPages = function () { + return [ + 'index', + 'privacy', + 'terms', + 'about', + 'contact', + 'what-is-cryptpad', + 'features', + 'faq', + 'maintenance' + ]; +}; + diff --git a/lib/load-config.js b/lib/load-config.js index 0756c2df4..1c502226a 100644 --- a/lib/load-config.js +++ b/lib/load-config.js @@ -1,7 +1,7 @@ /* jslint node: true */ "use strict"; var config; -var configPath = process.env.CRYPTPAD_CONFIG || "../config/config"; +var configPath = process.env.CRYPTPAD_CONFIG || "../config/config.js"; try { config = require(configPath); if (config.adminEmail === 'i.did.not.read.my.config@cryptpad.fr') { From 3df47a1415fed91e9a795199d1f49d0ff8f98e96 Mon Sep 17 00:00:00 2001 From: ansuz Date: Thu, 27 Feb 2020 13:24:19 -0500 Subject: [PATCH 02/27] continued WIP config reorganization --- config/config.example.js | 67 ++++++++++++++-------------------------- lib/defaults.js | 19 ++++++++++++ 2 files changed, 43 insertions(+), 43 deletions(-) diff --git a/config/config.example.js b/config/config.example.js index e2bcea5bc..0754b325b 100644 --- a/config/config.example.js +++ b/config/config.example.js @@ -19,6 +19,30 @@ var domain = ' ' + _domain; var Default = require("../lib/defaults"); module.exports = { + /* Sales coming from your server will be identified by your domain + * + * If you are using CryptPad in a business context, please consider taking a support contract + * by contacting sales@cryptpad.fr + */ + myDomain: _domain, + + // the address you want to bind to, :: means all ipv4 and ipv6 addresses + // this may not work on all operating systems + httpAddress: '::', + + // the port on which your httpd will listen + httpPort: 3000, + + // This is for allowing the cross-domain iframe to function when developing + httpSafePort: 3001, + + // This is for deployment in production, CryptPad uses a separate origin (domain) to host the + // cross-domain iframe. It can simply host the same content as CryptPad. + // httpSafeOrigin: "https://some-other-domain.xyz", + + httpUnsafeOrigin: domain, + + /* ===================== * Admin * ===================== */ @@ -51,22 +75,6 @@ module.exports = { * Infra setup * ===================== */ - // the address you want to bind to, :: means all ipv4 and ipv6 addresses - // this may not work on all operating systems - httpAddress: '::', - - // the port on which your httpd will listen - httpPort: 3000, - - // This is for allowing the cross-domain iframe to function when developing - httpSafePort: 3001, - - // This is for deployment in production, CryptPad uses a separate origin (domain) to host the - // cross-domain iframe. It can simply host the same content as CryptPad. - // httpSafeOrigin: "https://some-other-domain.xyz", - - httpUnsafeOrigin: domain, - /* Your CryptPad server will share this value with clients * via its /api/config endpoint. * @@ -127,13 +135,6 @@ module.exports = { */ adminEmail: 'i.did.not.read.my.config@cryptpad.fr', - /* Sales coming from your server will be identified by your domain - * - * If you are using CryptPad in a business context, please consider taking a support contract - * by contacting sales@cryptpad.fr - */ - myDomain: _domain, - /* * If you are using CryptPad internally and you want to increase the per-user storage limit, * change the following value. @@ -171,12 +172,6 @@ module.exports = { * STORAGE * ===================== */ - /* By default the CryptPad server will run scheduled tasks every five minutes - * If you want to run scheduled tasks in a separate process (like a crontab) - * you can disable this behaviour by setting the following value to true - */ - disableIntegratedTasks: false, - /* Pads that are not 'pinned' by any registered user can be set to expire * after a configurable number of days of inactivity (default 90 days). * The value can be changed or set to false to remove expiration. @@ -205,20 +200,6 @@ module.exports = { */ maxUploadSize: 20 * 1024 * 1024, - /* ===================== - * HARDWARE RELATED - * ===================== */ - - /* CryptPad's file storage adaptor closes unused files after a configurable - * number of milliseconds (default 30000 (30 seconds)) - */ - channelExpirationMs: 30000, - - /* CryptPad's file storage adaptor is limited by the number of open files. - * When the adaptor reaches openFileLimit, it will clean up older files - */ - openFileLimit: 2048, - /* ===================== * DATABASE VOLUMES * ===================== */ diff --git a/lib/defaults.js b/lib/defaults.js index f5d87b20b..fc807a2c7 100644 --- a/lib/defaults.js +++ b/lib/defaults.js @@ -63,3 +63,22 @@ Default.mainPages = function () { ]; }; +/* By default the CryptPad server will run scheduled tasks every five minutes + * If you want to run scheduled tasks in a separate process (like a crontab) + * you can disable this behaviour by setting the following value to true + */ + //disableIntegratedTasks: false, + + /* CryptPad's file storage adaptor closes unused files after a configurable + * number of milliseconds (default 30000 (30 seconds)) + */ +// channelExpirationMs: 30000, + + /* CryptPad's file storage adaptor is limited by the number of open files. + * When the adaptor reaches openFileLimit, it will clean up older files + */ + //openFileLimit: 2048, + + + + From e8fac0333a9d971e62ad41db6321bf7b743f6c5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Benqu=C3=A9?= Date: Fri, 28 Feb 2020 15:23:22 +0000 Subject: [PATCH 03/27] change order of contextual menu in Drive --- www/common/drive-ui.js | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/www/common/drive-ui.js b/www/common/drive-ui.js index 97d834a4e..4b0139500 100644 --- a/www/common/drive-ui.js +++ b/www/common/drive-ui.js @@ -325,6 +325,10 @@ define([ 'tabindex': '-1', 'data-icon': faOpenInCode, }, Messages.fc_openInCode)), + h('li', h('a.cp-app-drive-context-savelocal.dropdown-item', { + 'tabindex': '-1', + 'data-icon': 'fa-cloud-upload', + }, Messages.pad_mediatagImport)), // Save in your CryptDrive $separator.clone()[0], h('li', h('a.cp-app-drive-context-expandall.dropdown-item', { 'tabindex': '-1', @@ -344,14 +348,14 @@ define([ 'tabindex': '-1', 'data-icon': 'fa-shhare-alt', }, Messages.shareButton)), - h('li', h('a.cp-app-drive-context-savelocal.dropdown-item', { + h('li', h('a.cp-app-drive-context-access.dropdown-item', { 'tabindex': '-1', - 'data-icon': 'fa-cloud-upload', - }, Messages.pad_mediatagImport)), // Save in your CryptDrive - h('li', h('a.cp-app-drive-context-download.dropdown-item', { + 'data-icon': faAccess, + }, Messages.accessButton)), + h('li', h('a.cp-app-drive-context-properties.dropdown-item', { 'tabindex': '-1', - 'data-icon': faDownload, - }, Messages.download_mt_button)), + 'data-icon': faProperties, + }, Messages.fc_prop)), $separator.clone()[0], h('li', h('a.cp-app-drive-context-newfolder.dropdown-item.cp-app-drive-context-editable', { 'tabindex': '-1', @@ -458,14 +462,10 @@ define([ 'data-icon': faDelete, }, Messages.fc_remove_sharedfolder)), $separator.clone()[0], - h('li', h('a.cp-app-drive-context-access.dropdown-item', { - 'tabindex': '-1', - 'data-icon': faAccess, - }, "ACCESS")), // XXX - h('li', h('a.cp-app-drive-context-properties.dropdown-item', { + h('li', h('a.cp-app-drive-context-download.dropdown-item', { 'tabindex': '-1', - 'data-icon': faProperties, - }, Messages.fc_prop)), + 'data-icon': faDownload, + }, Messages.download_mt_button)), ]) ]); // add icons to the contextmenu options @@ -1279,7 +1279,7 @@ define([ case 'tree': show = ['open', 'openro', 'openincode', 'expandall', 'collapseall', 'color', 'download', 'share', 'savelocal', 'rename', 'delete', 'makeacopy', - 'deleteowned', 'removesf', 'properties', 'hashtag']; + 'deleteowned', 'removesf', 'access', 'properties', 'hashtag']; break; case 'default': show = ['open', 'openro', 'share', 'openparent', 'delete', 'deleteowned', 'properties', 'access', 'hashtag', 'makeacopy']; From 3cf09924aec87b7bd98876c54c19cd84d25d3213 Mon Sep 17 00:00:00 2001 From: ansuz Date: Fri, 28 Feb 2020 10:46:44 -0500 Subject: [PATCH 04/27] fix default CSP headers --- lib/defaults.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/defaults.js b/lib/defaults.js index fc807a2c7..6d8ec5e04 100644 --- a/lib/defaults.js +++ b/lib/defaults.js @@ -1,7 +1,9 @@ var Default = module.exports; Default.commonCSP = function (domain) { + domain = ' ' + domain; // Content-Security-Policy + return [ "default-src 'none'", "style-src 'unsafe-inline' 'self' " + domain, @@ -34,11 +36,11 @@ Default.commonCSP = function (domain) { }; Default.contentSecurity = function (domain) { - return Default.commonCSP(domain).join('; ') + "script-src 'self'" + domain; + return (Default.commonCSP(domain).join('; ') + "script-src 'self' " + domain).replace(/\s+/g, ' '); }; Default.padContentSecurity = function (domain) { - return Default.commonCSP(domain).join('; ') + "script-src 'self' 'unsafe-eval' 'unsafe-inline'" + domain; + return (Default.commonCSP(domain).join('; ') + "script-src 'self' 'unsafe-eval' 'unsafe-inline' " + domain).replace(/\s+/g, ' '); }; Default.httpHeaders = function () { From 94d8e7f2c2d8c3065e8cfa14db6c7dcaf15a7487 Mon Sep 17 00:00:00 2001 From: ansuz Date: Fri, 28 Feb 2020 10:49:20 -0500 Subject: [PATCH 05/27] provide a consistent type for 'customLimits' --- lib/historyKeeper.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/historyKeeper.js b/lib/historyKeeper.js index ed67602bd..95cb43e56 100644 --- a/lib/historyKeeper.js +++ b/lib/historyKeeper.js @@ -68,7 +68,7 @@ module.exports.create = function (config, cb) { allowSubscriptions: config.allowSubscriptions, myDomain: config.myDomain, mySubdomain: config.mySubdomain, - customLimits: config.customLimits, + customLimits: config.customLimits || {}, // FIXME this attribute isn't in the default conf // but it is referenced in Quota domain: config.domain From de6b9e2228c7537f77b3c80688d1468fa1c97d3e Mon Sep 17 00:00:00 2001 From: ansuz Date: Fri, 28 Feb 2020 10:50:30 -0500 Subject: [PATCH 06/27] apply some defaults when loading the config --- lib/load-config.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/lib/load-config.js b/lib/load-config.js index 1c502226a..0b861b826 100644 --- a/lib/load-config.js +++ b/lib/load-config.js @@ -18,5 +18,23 @@ try { } config = require("../config/config.example"); } + +var isPositiveNumber = function (n) { + return (!isNaN(n) && n >= 0); +}; + +if (!isPositiveNumber(config.inactiveTime)) { + config.inactiveTime = 90; +} +if (!isPositiveNumber(config.archiveRetentionTime)) { + config.archiveRetentionTime = 90; +} +if (!isPositiveNumber(config.maxUploadSize)) { + config.maxUploadSize = 20 * 1024 * 1024; +} +if (!isPositiveNumber(config.defaultStorageLimit)) { + config.defaultStorageLimit = 50 * 1024 * 1024; +} + module.exports = config; From 8219e5a903a6b844c58a6980ae13e643bb580c65 Mon Sep 17 00:00:00 2001 From: ansuz Date: Fri, 28 Feb 2020 11:41:02 -0500 Subject: [PATCH 07/27] Update issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 38 ++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..dd84ea782 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,38 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop (please complete the following information):** + - OS: [e.g. iOS] + - Browser [e.g. chrome, safari] + - Version [e.g. 22] + +**Smartphone (please complete the following information):** + - Device: [e.g. iPhone6] + - OS: [e.g. iOS8.1] + - Browser [e.g. stock browser, safari] + - Version [e.g. 22] + +**Additional context** +Add any other context about the problem here. From 0bbf35205beca071fd15a359b45247621afe2e26 Mon Sep 17 00:00:00 2001 From: ansuz Date: Fri, 28 Feb 2020 11:43:40 -0500 Subject: [PATCH 08/27] Update bug_report.md --- .github/ISSUE_TEMPLATE/bug_report.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index dd84ea782..d54278e84 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -10,6 +10,10 @@ assignees: '' **Describe the bug** A clear and concise description of what the bug is. +**Where did it happen?** +Did the issue occur on CryptPad.fr or an instance hosted by a third-party? +If on another instance, please provide its full URL. + **To Reproduce** Steps to reproduce the behavior: 1. Go to '...' From 03ff9bd0d77499be4bdb75efa414533065f85de2 Mon Sep 17 00:00:00 2001 From: ansuz Date: Fri, 28 Feb 2020 11:45:22 -0500 Subject: [PATCH 09/27] start deprecating usage of myDomain --- lib/historyKeeper.js | 3 ++- scripts/check-accounts.js | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/historyKeeper.js b/lib/historyKeeper.js index 95cb43e56..1d938ccfd 100644 --- a/lib/historyKeeper.js +++ b/lib/historyKeeper.js @@ -66,7 +66,8 @@ module.exports.create = function (config, cb) { flushCache: config.flushCache, adminEmail: config.adminEmail, allowSubscriptions: config.allowSubscriptions, - myDomain: config.myDomain, + myDomain: config.httpUnsafeOrigin, + // XXX not included in the config... mySubdomain: config.mySubdomain, customLimits: config.customLimits || {}, // FIXME this attribute isn't in the default conf diff --git a/scripts/check-accounts.js b/scripts/check-accounts.js index 4d0067d43..9e75da0c6 100644 --- a/scripts/check-accounts.js +++ b/scripts/check-accounts.js @@ -4,7 +4,7 @@ var Config = require("../lib/load-config"); var Package = require("../package.json"); var body = JSON.stringify({ - domain: Config.myDomain, + domain: Config.myDomain || Config.httpUnsafeOrigin, subdomain: Config.mySubdomain || null, adminEmail: Config.adminEmail, version: Package.version, From 8fd888108572ec70d9a809910e56512747aad187 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Benqu=C3=A9?= Date: Fri, 28 Feb 2020 16:58:05 +0000 Subject: [PATCH 10/27] remove XXX relating to translation keys --- www/common/common-ui-elements.js | 8 ++++---- www/common/inner/access.js | 27 +++------------------------ www/common/sframe-common-file.js | 3 --- 3 files changed, 7 insertions(+), 31 deletions(-) diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index 4f6e73ba0..d8f79d81e 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -2426,9 +2426,9 @@ define([ case 'access': button = $('