From 4ccbd2bbc11b81686a1ea1d031a89461a137f8d3 Mon Sep 17 00:00:00 2001 From: YJ Date: Wed, 17 Apr 2019 12:16:58 +0200 Subject: [PATCH 01/12] init --- packages/electron-app/README.md | 20 ++++++++++++++++++++ packages/light-apps/public/index.html | 9 --------- packages/light-apps/public/manifest.json | 4 ++-- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/packages/electron-app/README.md b/packages/electron-app/README.md index 0727535bd..b5dcb70a1 100644 --- a/packages/electron-app/README.md +++ b/packages/electron-app/README.md @@ -11,3 +11,23 @@ This command assumes that we've built a CRA app inside `packages/light-apps`. It ### `yarn start` Runs `electron-webpack dev`, which tells Electron to load http://localhost:3000, which is most likely the port on which CRA's dev mode runs. It reloads Electron on any code change inside the electron codebase. + +## Electron Security Checklist: +https://electronjs.org/docs/tutorial/security#1-only-load-secure-content + +Inspired by: https://github.com/paritytech/fether/pull/451 + +#### Cheatsheet +1. Only Load Secure Content (https/wss/ftps over http/ws/ftp) +2. Disable Node.js Integration for Remote Content + * Prevents XSS attacks from escalating to a Remote Code Execution Attack - limits the attack surface to the renderer process. +
+  const mainWindow = new BrowserWindow({
+    webPreferences: {
+      nodeIntegration: false,
+      nodeIntegrationInWorker: false,
+      preload: path.join(app.getAppPath(), 'preload.js')
+    }
+    })
+  
+3. diff --git a/packages/light-apps/public/index.html b/packages/light-apps/public/index.html index 225662bc0..3f57904a3 100644 --- a/packages/light-apps/public/index.html +++ b/packages/light-apps/public/index.html @@ -26,15 +26,6 @@ You need to enable JavaScript to run this app.
- diff --git a/packages/light-apps/public/manifest.json b/packages/light-apps/public/manifest.json index 1f2f141fa..1bdfe6010 100644 --- a/packages/light-apps/public/manifest.json +++ b/packages/light-apps/public/manifest.json @@ -1,6 +1,6 @@ { - "short_name": "React App", - "name": "Create React App Sample", + "short_name": "SLUI", + "name": "Substrate Light UI", "icons": [ { "src": "favicon.ico", From 22276018a42796f01c5680781267f7e2b7430c3c Mon Sep 17 00:00:00 2001 From: YJ Date: Thu, 18 Apr 2019 17:01:36 +0200 Subject: [PATCH 02/12] update with needed permissions --- packages/electron-app/README.md | 103 +++++++++++++++++++++++++++++--- 1 file changed, 95 insertions(+), 8 deletions(-) diff --git a/packages/electron-app/README.md b/packages/electron-app/README.md index b5dcb70a1..179f15999 100644 --- a/packages/electron-app/README.md +++ b/packages/electron-app/README.md @@ -21,13 +21,100 @@ Inspired by: https://github.com/paritytech/fether/pull/451 1. Only Load Secure Content (https/wss/ftps over http/ws/ftp) 2. Disable Node.js Integration for Remote Content * Prevents XSS attacks from escalating to a Remote Code Execution Attack - limits the attack surface to the renderer process. + * **Node Integration + XSS in renderer process = RCE**
-  const mainWindow = new BrowserWindow({
-    webPreferences: {
-      nodeIntegration: false,
-      nodeIntegrationInWorker: false,
-      preload: path.join(app.getAppPath(), 'preload.js')
-    }
-    })
+    const mainWindow = new BrowserWindow({
+      webPreferences: {
+        nodeIntegration: false,
+        nodeIntegrationInWorker: false,
+        preload: path.join(app.getAppPath(), 'preload.js')
+      }
+    });
   
-3. + * Good: instead of allowing full access to the Node API (including stuff like fs, io, etc.), only export necessary features via a preload script, making sure to validate arguments properly. + + **N.B. SLUI: preload not necessary, as there's no need for main<->renderer communication (yet)** +3. Context Isolation - separates Javascript contexts between preload scripts and the page's scripts, and between Electon's internal scripts and the page's scripts, preventing so-called "Prototype Pollution Attacks", i.e. extra protection against RCE's. + * `contextIsolation` is false by default. + * this means by default, you have shared context between the preload scripts and the page's scripts, i.e. `window.variable` set in `preload.js` is defined in the `BrowserWindow`'s context. + + **N.B. SLUI: again not a concern considering we don't need preload scripts at all, but good to keep in mind.** +4. Handle Session Permission Requests from Remote Content + * The default setting in Electron is to approve all permission requests unless the developer explicitly tells it to handle it a particular way. + **N.B. SLUI: only some permissions matter in our context.** + Required Permissions: + ``` + contentSettings + debugger: only Dev. + desktopCapture: only Dev. + fileBrowserHandler: This is needed for JSON File Recovery. + idle: It could be a useful security measure in case user is AFK + notifications: Yes - extend from Alerts. + ``` + + + * Electron implements the same types of permissions as Chromium as listed below: + ``` + activeTab: we don't use tabs + alarms: not needed + background: not needed + bookmarks: not needed + browsingData: not needed + certificateProvider: yes + clipboardRead: no + clipboardWrite: no + contentSettings: only allow https, ftps, wss + contextMenus: no + cookies: no + debugger: not needed in production, only in development environment. + declarativeContent + declarativeNetRequest: cannot see a need to block or redirect network requests ATOW. + declarativeWebRequest: cannot see a need to block or redirect network requests ATOW. + desktopCapture: disable in Production, enable in Development. + displaySource: no. + dns: no. + documentScan: no + downloads: no. + enterprise.deviceAttributes: no. + enterprise.hardwarePlatform: no. + enterprise.platformKeys: no. + experimental: no. + fileBrowserHandler: This is needed for JSON File Recovery. + fileSystemProvider: no need + fontSettings: no need + gcm: no need + geolocation: definitely no need for this. + history: no need | using react router + identity: no need + idle: It could be a useful security measure in case user is AFK + management: no need + nativeMessaging: no need + networking.config: no need + notifications: Yes. + pageCapture: no need + platformKeys: no need. + power: no need. + printerProvider: no need. + privacy: no need. + processes: no. + proxy: no. + sessions: no. + signedInDevices: no. + storage: no. + system.cpu: no + system.display: no + system.memory: no + system.storage: no + tabCapture: no. + tabs: no need + topSites: no + tts: nice for accessibility in the future but honestly probably not necessary. + ttsEngine: nice for accessibility in the future but honestly probably not necessary. + unlimitedStorage + vpnProvider: no + wallpaper: not needed + webNavigation: no + webRequest: no + webRequestBlocking: no + ``` +5. From f93b6c121b5c4c1c49622ba95906cd130a5fb503 Mon Sep 17 00:00:00 2001 From: YJ Date: Thu, 18 Apr 2019 17:07:35 +0200 Subject: [PATCH 03/12] update with needed permissions --- packages/electron-app/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/electron-app/README.md b/packages/electron-app/README.md index 179f15999..c6a24d822 100644 --- a/packages/electron-app/README.md +++ b/packages/electron-app/README.md @@ -52,7 +52,6 @@ Inspired by: https://github.com/paritytech/fether/pull/451 notifications: Yes - extend from Alerts. ``` - * Electron implements the same types of permissions as Chromium as listed below: ``` activeTab: we don't use tabs @@ -117,4 +116,6 @@ Inspired by: https://github.com/paritytech/fether/pull/451 webRequest: no webRequestBlocking: no ``` -5. +5. Do Not Disable WebSecurity (default) - self explanatory +6. Define a Content Security Policy + * From c115dc19ab0f56804af2be1a9698c524f3c0826e Mon Sep 17 00:00:00 2001 From: YJ Date: Thu, 18 Apr 2019 17:44:38 +0200 Subject: [PATCH 04/12] nbs --- packages/electron-app/README.md | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/packages/electron-app/README.md b/packages/electron-app/README.md index c6a24d822..f08ee44e0 100644 --- a/packages/electron-app/README.md +++ b/packages/electron-app/README.md @@ -117,5 +117,29 @@ Inspired by: https://github.com/paritytech/fether/pull/451 webRequestBlocking: no ``` 5. Do Not Disable WebSecurity (default) - self explanatory -6. Define a Content Security Policy - * +6. Define a Content Security Policy - not relevant (yet) as we're not loading any external web pages +7. Do Not Set allowRunningInsecureContent to true (default) - self explanatory +8. Do Not Enable Experimental Features (default) - self explanatory +9. Do Not Use enableBlinkFeatures (default) - self explanatory +10. Do Not Use allowpopups (default) - self explanatory +11. Verify WebView Options Before Creation: + * A WebView created in the renderer process will always create its own renderer process using its own `webPreferences`. + ``` + app.on('web-contents-created', (event, contents) => { + contents.on('will-attach-webview', (event, webPreferences, params) => { + // Strip away preload scripts if unused or verify their location is legitimate + delete webPreferences.preload + delete webPreferences.preloadURL + + // Disable Node.js integration + webPreferences.nodeIntegration = false + + // Verify URL being loaded + if (!params.src.startsWith('https://example.com/')) { + event.preventDefault() + } + }) + }) + ``` + **N.B. SLUI: we don't load any webpages, and if we do in the future it'll be in a browser so this is not a concern.** +12. From 8a4f51f5470225bccb6ca3896f649b95e307c551 Mon Sep 17 00:00:00 2001 From: YJ Date: Thu, 18 Apr 2019 17:59:58 +0200 Subject: [PATCH 05/12] checklist cheatsheet --- packages/electron-app/README.md | 39 ++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/packages/electron-app/README.md b/packages/electron-app/README.md index f08ee44e0..e4aa075d4 100644 --- a/packages/electron-app/README.md +++ b/packages/electron-app/README.md @@ -142,4 +142,41 @@ Inspired by: https://github.com/paritytech/fether/pull/451 }) ``` **N.B. SLUI: we don't load any webpages, and if we do in the future it'll be in a browser so this is not a concern.** -12. +12. Disable or limit navigation +``` + const URL = require('url').URL + + app.on('web-contents-created', (event, contents) => { + contents.on('will-navigate', (event, navigationUrl) => { + const parsedUrl = new URL(navigationUrl) + + if (parsedUrl.origin !== 'https://example.com') { + event.preventDefault() + } + }) + }) +``` +**N.B. SLUI: While not used yet, we may in the future want to navigate to the api docs page, or the forum, or other substrate related sites.** + +13. Disable or limit creation of new windows +``` +const { shell } = require('electron') + +app.on('web-contents-created', (event, contents) => { + contents.on('new-window', (event, navigationUrl) => { + // if somehow there is a new-window event, block it. + event.preventDefault() + }) +}) +``` +**N.B. SLUI: we just need the one BrowserWindow** +14. Do not use openExternal with untrusted content +15. Disable the remote module: the `remote` module would allow the renderer process to access APIs normally only available in the main process. +``` + const mainWindow = new BrowserWindow({ + webPreferences: { + enableRemoteModule: false + } + }) +``` +16. Filter the remote module: relevant only if we cannot disable remote module. From 0dd937abb1b5a9b92edb7266840e180438cc17c5 Mon Sep 17 00:00:00 2001 From: YJ Date: Tue, 23 Apr 2019 10:20:22 +0200 Subject: [PATCH 06/12] set web preferences --- packages/electron-app/src/main/index.ts | 34 ++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/packages/electron-app/src/main/index.ts b/packages/electron-app/src/main/index.ts index 96983a14f..0cdbb7c92 100644 --- a/packages/electron-app/src/main/index.ts +++ b/packages/electron-app/src/main/index.ts @@ -12,11 +12,32 @@ import { staticPath } from './util/staticPath'; const { app, BrowserWindow } = electron; let mainWindow: Electron.BrowserWindow | undefined; +// https://electronjs.org/docs/tutorial/security#electron-security-warnings +process.env.ELECTRON_ENABLE_SECURITY_WARNINGS = true; + function createWindow () { mainWindow = new BrowserWindow({ height: 1920, resizable: true, - width: 1440 + width: 1440, + webPreferences: { + allowRunningInsecureContent: false, + devTools: true, + enableBlinkFeatures: '', // https://electronjs.org/docs/tutorial/security#9-do-not-use-enableblinkfeatures + enableRemoteModule: false, + experimentalFeatures: false, // Do not set to true + contextIsolation: true, // prevent context sharing between renderer<->main processes + navigateOnDragDrop: false, + nativeWindowOpen: true, + nodeIntegration: false, // https://electronjs.org/docs/tutorial/security#2-disable-nodejs-integration-for-remote-content + nodeIntegrationInWorker: false, // https://electronjs.org/docs/tutorial/security#2-disable-nodejs-integration-for-remote-content + plugins: false, + sandbox: true, // isolate all BrowserWindow instance environments + webSecurity: true, // https://electronjs.org/docs/tutorial/security#5-do-not-disable-websecurity + webviewTag: false, // Associated with `will-attach-webview` + safeDialogs: true, + safeDialogsMessage: 'Electron consecutive dialog protection was triggered' + } }); mainWindow.loadURL( @@ -49,6 +70,17 @@ app.on('activate', function () { } }); +app.on('web-contents-created', (event, contents) => { + contents.on('will-attach-webview', (event, webPreferences, params) => { + // Strip away preload scripts if unused or verify their location is legitimate + delete webPreferences.preload; + delete webPreferences.preloadURL; + + // Disable Node.js integration + webPreferences.nodeIntegration = false; + }); +}); + // Quit when all windows are closed. app.on('window-all-closed', function () { // On OS X it is common for applications and their menu bar From 8dc9540edbb901c3a1cd0795242f2bfae1313037 Mon Sep 17 00:00:00 2001 From: YJ Date: Tue, 23 Apr 2019 14:36:01 +0200 Subject: [PATCH 07/12] lint --- packages/electron-app/src/main/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/electron-app/src/main/index.ts b/packages/electron-app/src/main/index.ts index 0cdbb7c92..43193ada2 100644 --- a/packages/electron-app/src/main/index.ts +++ b/packages/electron-app/src/main/index.ts @@ -13,7 +13,7 @@ const { app, BrowserWindow } = electron; let mainWindow: Electron.BrowserWindow | undefined; // https://electronjs.org/docs/tutorial/security#electron-security-warnings -process.env.ELECTRON_ENABLE_SECURITY_WARNINGS = true; +process.env.ELECTRON_ENABLE_SECURITY_WARNINGS = 'true'; function createWindow () { mainWindow = new BrowserWindow({ From 41677e79719b9015b7dcd0a42640838a02a7cd11 Mon Sep 17 00:00:00 2001 From: YJ Date: Mon, 29 Apr 2019 10:55:03 +0200 Subject: [PATCH 08/12] feat(csp):use the csp from parity-js shell and fether --- packages/electron-app/src/main/util/csp.ts | 56 ++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 packages/electron-app/src/main/util/csp.ts diff --git a/packages/electron-app/src/main/util/csp.ts b/packages/electron-app/src/main/util/csp.ts new file mode 100644 index 000000000..e9dd17bdd --- /dev/null +++ b/packages/electron-app/src/main/util/csp.ts @@ -0,0 +1,56 @@ + +const IS_PROD = process.env.NODE_ENV === 'production'; + +/* eslint-disable */ +// References: +// * https://github.com/parity-js/shell +// * https://github.com/paritytech/fether +const CSP_CONFIG = { + // Disallow mixed content + blockAllMixedContent: 'block-all-mixed-content;', + // Disallow framing and web workers. + // tslint:disable-next-line:quotemark + childSrc: "child-src 'none';", + // FIXME - Only allow connecting to WSS and HTTPS servers. + connectSrc: 'connect-src http: ws:;', + // Fallback for missing directives. + // Reference: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/default-src + // + // Disallow everything as fallback by default for all CSP fetch directives. + defaultSrc: "default-src 'none';", + // Disallow fonts. + fontSrc: "font-src 'none';", // Additionally used in Parity-JS Shell `'self' data: https:` + // Disallow submitting any forms + formAction: "form-action 'none';", + // Disallow framing. + frameSrc: "frame-src 'none';", + imgSrc: !IS_PROD + ? // Only allow HTTPS for images. Token provider logos must be https:// + // Allow `data:` `blob:`. + "img-src 'self' 'unsafe-inline' file: data: blob: https:;" + : // Only allow HTTPS for images. Token provider logos must be https:// + // Allow `data:` `blob:`. + "img-src 'unsafe-inline' file: data: blob: https:;", // Additionally used in Parity-JS Shell `'self'` + // Disallow manifests. + manifestSrc: "manifest-src 'none';", + // Disallow media. + mediaSrc: "media-src 'none';", + // Disallow fonts and `` objects + objectSrc: "object-src 'none';", + // Disallow prefetching. + prefetchSrc: "prefetch-src 'none';", + scriptSrc: !IS_PROD + ? // Only allow `http:` and `unsafe-eval` in dev mode (required by create-react-app) + "script-src 'self' file: http: blob: 'unsafe-inline' 'unsafe-eval';" + : "script-src file: 'unsafe-inline';", + styleSrc: !IS_PROD + ? "style-src 'self' 'unsafe-inline' file: blob:;" // Additionally used in Parity-JS Shell `data: https:` + : "style-src unsafe-inline' file: blob:;", // Additionally used in Parity-JS Shell `data: https:` + // Allow `blob:` for camera access (worker) + workerSrc: 'worker-src blob:;' // Additionally used in Parity-JS Shell `'self' https:` +}; +/* eslint-enable */ + +const CSP = Object.values(CSP_CONFIG).join(' '); + +export { CSP }; From e21293e89a01ced653dacf545fddc256ff0c9c1a Mon Sep 17 00:00:00 2001 From: YJ Date: Mon, 29 Apr 2019 11:24:21 +0200 Subject: [PATCH 09/12] fix: set csp on headers received --- packages/electron-app/package.json | 1 + packages/electron-app/src/main/index.ts | 31 ++++++++++--- .../electron-app/src/main/util/constants.ts | 5 +++ packages/electron-app/src/main/util/csp.ts | 5 ++- .../src/main/util/declarations/pino.d.ts | 1 + packages/electron-app/src/main/util/index.ts | 7 +++ yarn.lock | 44 +++++++++++++++++++ 7 files changed, 87 insertions(+), 7 deletions(-) create mode 100644 packages/electron-app/src/main/util/constants.ts create mode 100644 packages/electron-app/src/main/util/declarations/pino.d.ts create mode 100644 packages/electron-app/src/main/util/index.ts diff --git a/packages/electron-app/package.json b/packages/electron-app/package.json index c86d14c12..e3c29dd7e 100644 --- a/packages/electron-app/package.json +++ b/packages/electron-app/package.json @@ -27,6 +27,7 @@ "dependencies": { "@types/electron-devtools-installer": "^2.2.0", "electron-devtools-installer": "^2.2.4", + "pino": "^5.12.3", "source-map-support": "^0.5.10" } } diff --git a/packages/electron-app/src/main/index.ts b/packages/electron-app/src/main/index.ts index 43193ada2..d55d3a052 100644 --- a/packages/electron-app/src/main/index.ts +++ b/packages/electron-app/src/main/index.ts @@ -4,12 +4,14 @@ import electron from 'electron'; import installExtension, { REACT_DEVELOPER_TOOLS } from 'electron-devtools-installer'; +import Pino from 'pino'; import path from 'path'; import url from 'url'; -import { staticPath } from './util/staticPath'; +import { CSP, IS_PROD, staticPath } from './util'; -const { app, BrowserWindow } = electron; +const { app, BrowserWindow, session } = electron; +const pino = Pino(); let mainWindow: Electron.BrowserWindow | undefined; // https://electronjs.org/docs/tutorial/security#electron-security-warnings @@ -22,21 +24,21 @@ function createWindow () { width: 1440, webPreferences: { allowRunningInsecureContent: false, + contextIsolation: true, // prevent context sharing between renderer<->main processes devTools: true, enableBlinkFeatures: '', // https://electronjs.org/docs/tutorial/security#9-do-not-use-enableblinkfeatures enableRemoteModule: false, experimentalFeatures: false, // Do not set to true - contextIsolation: true, // prevent context sharing between renderer<->main processes navigateOnDragDrop: false, nativeWindowOpen: true, nodeIntegration: false, // https://electronjs.org/docs/tutorial/security#2-disable-nodejs-integration-for-remote-content nodeIntegrationInWorker: false, // https://electronjs.org/docs/tutorial/security#2-disable-nodejs-integration-for-remote-content plugins: false, sandbox: true, // isolate all BrowserWindow instance environments - webSecurity: true, // https://electronjs.org/docs/tutorial/security#5-do-not-disable-websecurity - webviewTag: false, // Associated with `will-attach-webview` safeDialogs: true, - safeDialogsMessage: 'Electron consecutive dialog protection was triggered' + safeDialogsMessage: 'Electron consecutive dialog protection was triggered', + webSecurity: true, // https://electronjs.org/docs/tutorial/security#5-do-not-disable-websecurity + webviewTag: false // Associated with `will-attach-webview` } }); @@ -55,6 +57,23 @@ function createWindow () { .catch((err: string) => console.log('An error occurred: ', err)); } + // Content Security Policy (CSP) + // @ts-ignore session object will always be defined + session.defaultSession.webRequest.onHeadersReceived((details, callback) => { + pino.debug( + `Configuring Content-Security-Policy for environment ${ + IS_PROD ? 'production' : 'development' + }` + ); + + callback({ + responseHeaders: { + ...details.responseHeaders, + 'Content-Security-Policy': [CSP] + } + }); + }); + mainWindow.on('closed', () => { mainWindow = undefined; }); diff --git a/packages/electron-app/src/main/util/constants.ts b/packages/electron-app/src/main/util/constants.ts new file mode 100644 index 000000000..b843e2b6e --- /dev/null +++ b/packages/electron-app/src/main/util/constants.ts @@ -0,0 +1,5 @@ +// Copyright 2018-2019 @paritytech/substrate-light-ui authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +export const IS_PROD = process.env.NODE_ENV === 'production'; \ No newline at end of file diff --git a/packages/electron-app/src/main/util/csp.ts b/packages/electron-app/src/main/util/csp.ts index e9dd17bdd..a2e5332d1 100644 --- a/packages/electron-app/src/main/util/csp.ts +++ b/packages/electron-app/src/main/util/csp.ts @@ -1,5 +1,8 @@ +// Copyright 2018-2019 @paritytech/substrate-light-ui authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. -const IS_PROD = process.env.NODE_ENV === 'production'; +import { IS_PROD } from './constants'; /* eslint-disable */ // References: diff --git a/packages/electron-app/src/main/util/declarations/pino.d.ts b/packages/electron-app/src/main/util/declarations/pino.d.ts new file mode 100644 index 000000000..df978563c --- /dev/null +++ b/packages/electron-app/src/main/util/declarations/pino.d.ts @@ -0,0 +1 @@ +declare module 'pino'; \ No newline at end of file diff --git a/packages/electron-app/src/main/util/index.ts b/packages/electron-app/src/main/util/index.ts new file mode 100644 index 000000000..cef6d331b --- /dev/null +++ b/packages/electron-app/src/main/util/index.ts @@ -0,0 +1,7 @@ +// Copyright 2018-2019 @paritytech/substrate-light-ui authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +export * from './constants'; +export * from './csp'; +export * from './staticPath'; \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index b7895c05c..c9bc35fdf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8578,6 +8578,16 @@ fast-levenshtein@~2.0.4: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= +fast-redact@^1.4.4: + version "1.5.0" + resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-1.5.0.tgz#302892f566750c4f5eec7b830bfc9bc473484034" + integrity sha512-Afo61CgUjkzdvOKDHn08qnZ0kwck38AOGcMlvSGzvJbIab6soAP5rdoQayecGCDsD69AiF9vJBXyq31eoEO2tQ== + +fast-safe-stringify@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.6.tgz#04b26106cc56681f51a044cfc0d76cf0008ac2c2" + integrity sha512-q8BZ89jjc+mz08rSxROs8VsrBBcn1SIw1kq9NjolL509tkABRk9io01RAjSaEv1Xb2uFLt8VtRiZbGp5H8iDtg== + fastparse@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9" @@ -8828,6 +8838,11 @@ flat-cache@^1.2.1: rimraf "~2.6.2" write "^0.2.1" +flatstr@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/flatstr/-/flatstr-1.0.9.tgz#0950d56fec02de1030c1311847ecd58c25690eb9" + integrity sha512-qFlJnOBWDfIaunF54/lBqNKmXOI0HqNhu+mHkLmbaBXlS71PUd9OjFOdyevHt/aHoHB1+eW7eKHgRKOG5aHSpw== + flatten@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782" @@ -13775,6 +13790,23 @@ pinkie@^2.0.0: resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= +pino-std-serializers@^2.3.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-2.4.0.tgz#c0588b5ab0905ac55bae2cb61639ed93153681fb" + integrity sha512-ysT2ylXu1aEec9k8cm/lz7emBcfpdxFWHqvHeGXf1wvfw7TKPMGhLWwS+ciHw6u4ffnmV+pkAMF4MUIZmZZdSg== + +pino@^5.12.3: + version "5.12.3" + resolved "https://registry.yarnpkg.com/pino/-/pino-5.12.3.tgz#5ebc7d15b3584b91de8d3cdae01ef3a10e7fb977" + integrity sha512-/PiX7QXOMZz7edRVGm/apt22nkdRByB6ki0ftWcDpHjjNmjnE7UubNd7NeDX7cBey27obxvBvZy3oQuJbz1+Ag== + dependencies: + fast-redact "^1.4.4" + fast-safe-stringify "^2.0.6" + flatstr "^1.0.9" + pino-std-serializers "^2.3.0" + quick-format-unescaped "^3.0.2" + sonic-boom "^0.7.3" + pirates@^4.0.0, pirates@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87" @@ -15105,6 +15137,11 @@ querystringify@^2.0.0: resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e" integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA== +quick-format-unescaped@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-3.0.2.tgz#0137e94d8fb37ffeb70040535111c378e75396fb" + integrity sha512-FXTaCkwvpIlkdKeGDNgcq07SXWS383noQUuZjvdE1QcTt+eLuqof6/BDiEPqB59FWLie/l91+HtlJSw7iCViSA== + quick-lru@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-1.1.0.tgz#4360b17c61136ad38078397ff11416e186dcfbb8" @@ -16649,6 +16686,13 @@ socks@~2.3.2: ip "^1.1.5" smart-buffer "4.0.2" +sonic-boom@^0.7.3: + version "0.7.3" + resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-0.7.3.tgz#cbfc18e87c2b8078b00e38ad9475c05fce5ea696" + integrity sha512-A9EyoIeLD+g9vMLYQKjNCatJtAKdBQMW03+L8ZWWX/A6hq+srRCwdqHrBD1R8oSMLXov3oHN13dljtZf12q2Ow== + dependencies: + flatstr "^1.0.9" + sort-keys@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad" From 7a294f47dfe0725f373ba3fc88bd80569f475d8b Mon Sep 17 00:00:00 2001 From: YJ Date: Mon, 29 Apr 2019 12:02:12 +0200 Subject: [PATCH 10/12] fix lint --- packages/electron-app/src/main/util/constants.ts | 2 +- packages/electron-app/src/main/util/index.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/electron-app/src/main/util/constants.ts b/packages/electron-app/src/main/util/constants.ts index b843e2b6e..960b0f70f 100644 --- a/packages/electron-app/src/main/util/constants.ts +++ b/packages/electron-app/src/main/util/constants.ts @@ -2,4 +2,4 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. -export const IS_PROD = process.env.NODE_ENV === 'production'; \ No newline at end of file +export const IS_PROD = process.env.NODE_ENV === 'production'; diff --git a/packages/electron-app/src/main/util/index.ts b/packages/electron-app/src/main/util/index.ts index cef6d331b..fc9bab9b9 100644 --- a/packages/electron-app/src/main/util/index.ts +++ b/packages/electron-app/src/main/util/index.ts @@ -4,4 +4,4 @@ export * from './constants'; export * from './csp'; -export * from './staticPath'; \ No newline at end of file +export * from './staticPath'; From e5757b5f5cec81d43cab4cfa94f7c97e23619578 Mon Sep 17 00:00:00 2001 From: YJ Date: Mon, 29 Apr 2019 14:30:50 +0200 Subject: [PATCH 11/12] fix: font src csp, comment out webview event --- packages/electron-app/src/main/index.ts | 19 +++++++----------- packages/electron-app/src/main/util/csp.ts | 2 +- yarn.lock | 23 +++++++++------------- 3 files changed, 17 insertions(+), 27 deletions(-) diff --git a/packages/electron-app/src/main/index.ts b/packages/electron-app/src/main/index.ts index d55d3a052..23a30f4c7 100644 --- a/packages/electron-app/src/main/index.ts +++ b/packages/electron-app/src/main/index.ts @@ -58,8 +58,7 @@ function createWindow () { } // Content Security Policy (CSP) - // @ts-ignore session object will always be defined - session.defaultSession.webRequest.onHeadersReceived((details, callback) => { + session.defaultSession!.webRequest.onHeadersReceived((details, callback) => { pino.debug( `Configuring Content-Security-Policy for environment ${ IS_PROD ? 'production' : 'development' @@ -89,16 +88,12 @@ app.on('activate', function () { } }); -app.on('web-contents-created', (event, contents) => { - contents.on('will-attach-webview', (event, webPreferences, params) => { - // Strip away preload scripts if unused or verify their location is legitimate - delete webPreferences.preload; - delete webPreferences.preloadURL; - - // Disable Node.js integration - webPreferences.nodeIntegration = false; - }); -}); +// Uncomment this block if ever we decide to use a webview in the app. +// app.on('web-contents-created', (event, contents) => { +// contents.on('will-attach-webview', (event, webPreferences, params) => { +// event.preventDefault(); +// }); +// }); // Quit when all windows are closed. app.on('window-all-closed', function () { diff --git a/packages/electron-app/src/main/util/csp.ts b/packages/electron-app/src/main/util/csp.ts index a2e5332d1..384e8263a 100644 --- a/packages/electron-app/src/main/util/csp.ts +++ b/packages/electron-app/src/main/util/csp.ts @@ -22,7 +22,7 @@ const CSP_CONFIG = { // Disallow everything as fallback by default for all CSP fetch directives. defaultSrc: "default-src 'none';", // Disallow fonts. - fontSrc: "font-src 'none';", // Additionally used in Parity-JS Shell `'self' data: https:` + fontSrc: "font-src 'self';", // Additionally used in Parity-JS Shell `'self' data: https:` // Disallow submitting any forms formAction: "form-action 'none';", // Disallow framing. diff --git a/yarn.lock b/yarn.lock index 27883bb5b..4c16cfc6c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3213,11 +3213,6 @@ "@types/styled-components" "*" csstype "^2.2.0" -"@types/tapable@1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.2.tgz#e13182e1b69871a422d7863e11a4a6f5b814a4bd" - integrity sha512-42zEJkBpNfMEAvWR5WlwtTH22oDzcMjFsL9gDGExwF8X8WvAiw7Vwop7hPw03QT8TKfec83LwbHj6SvpqM4ELQ== - "@types/unist@*", "@types/unist@^2.0.0", "@types/unist@^2.0.2": version "2.0.3" resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.3.tgz#9c088679876f374eb5983f150d4787aa6fb32d7e" @@ -8381,16 +8376,16 @@ flat-cache@^2.0.1: rimraf "2.6.3" write "1.0.3" -flatted@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.0.tgz#55122b6536ea496b4b44893ee2608141d10d9916" - integrity sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg== - flatstr@^1.0.9: version "1.0.9" resolved "https://registry.yarnpkg.com/flatstr/-/flatstr-1.0.9.tgz#0950d56fec02de1030c1311847ecd58c25690eb9" integrity sha512-qFlJnOBWDfIaunF54/lBqNKmXOI0HqNhu+mHkLmbaBXlS71PUd9OjFOdyevHt/aHoHB1+eW7eKHgRKOG5aHSpw== +flatted@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.0.tgz#55122b6536ea496b4b44893ee2608141d10d9916" + integrity sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg== + flatten@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782" @@ -9291,10 +9286,10 @@ html-to-react@^1.3.4: lodash.camelcase "^4.3.0" ramda "^0.26" -html-webpack-plugin@4.0.0-alpha.2: - version "4.0.0-alpha.2" - resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-4.0.0-alpha.2.tgz#7745967e389a57a098e26963f328ebe4c19b598d" - integrity sha512-tyvhjVpuGqD7QYHi1l1drMQTg5i+qRxpQEGbdnYFREgOKy7aFDf/ocQ/V1fuEDlQx7jV2zMap3Hj2nE9i5eGXw== +html-webpack-plugin@4.0.0-beta.5, html-webpack-plugin@^4.0.0-beta.2: + version "4.0.0-beta.5" + resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-4.0.0-beta.5.tgz#2c53083c1151bfec20479b1f8aaf0039e77b5513" + integrity sha512-y5l4lGxOW3pz3xBTFdfB9rnnrWRPVxlAhX6nrBYIcW+2k2zC3mSp/3DxlWVCMBfnO6UAnoF8OcFn0IMy6kaKAQ== dependencies: html-minifier "^3.5.20" loader-utils "^1.1.0" From 7d1fc1ca1a7f5a211efeff4117935bba965187a4 Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Tue, 30 Apr 2019 11:55:25 +0200 Subject: [PATCH 12/12] Improve CSP (#303) * fix(csp): Make CSP work * fix: Remove unsafe-eval --- packages/electron-app/src/main/index.ts | 9 ++-- packages/electron-app/src/main/util/csp.ts | 42 +++++++---------- packages/light-apps/public/index.html | 52 +++++++++++++++------- 3 files changed, 56 insertions(+), 47 deletions(-) diff --git a/packages/electron-app/src/main/index.ts b/packages/electron-app/src/main/index.ts index 23a30f4c7..d1a46e66a 100644 --- a/packages/electron-app/src/main/index.ts +++ b/packages/electron-app/src/main/index.ts @@ -8,7 +8,7 @@ import Pino from 'pino'; import path from 'path'; import url from 'url'; -import { CSP, IS_PROD, staticPath } from './util'; +import { CSP, staticPath } from './util'; const { app, BrowserWindow, session } = electron; const pino = Pino(); @@ -59,10 +59,11 @@ function createWindow () { // Content Security Policy (CSP) session.defaultSession!.webRequest.onHeadersReceived((details, callback) => { + // Note: `onHeadersReceived` will not be called in prod, because we use the + // file:// protocol: https://electronjs.org/docs/tutorial/security#csp-meta-tag + // Instead, the CSP are the ones in the meta tag inside index.html pino.debug( - `Configuring Content-Security-Policy for environment ${ - IS_PROD ? 'production' : 'development' - }` + 'Configuring Content-Security-Policy for environment development' ); callback({ diff --git a/packages/electron-app/src/main/util/csp.ts b/packages/electron-app/src/main/util/csp.ts index 384e8263a..9f5a809f0 100644 --- a/packages/electron-app/src/main/util/csp.ts +++ b/packages/electron-app/src/main/util/csp.ts @@ -4,7 +4,6 @@ import { IS_PROD } from './constants'; -/* eslint-disable */ // References: // * https://github.com/parity-js/shell // * https://github.com/paritytech/fether @@ -12,48 +11,37 @@ const CSP_CONFIG = { // Disallow mixed content blockAllMixedContent: 'block-all-mixed-content;', // Disallow framing and web workers. - // tslint:disable-next-line:quotemark childSrc: "child-src 'none';", // FIXME - Only allow connecting to WSS and HTTPS servers. - connectSrc: 'connect-src http: ws:;', + connectSrc: IS_PROD + ? 'connect-src ws:;' + // Also allow http in dev mode, for CRA + : 'connect-src http: ws:;', // Fallback for missing directives. // Reference: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/default-src // // Disallow everything as fallback by default for all CSP fetch directives. defaultSrc: "default-src 'none';", - // Disallow fonts. - fontSrc: "font-src 'self';", // Additionally used in Parity-JS Shell `'self' data: https:` + // Disallow fonts, we allow https because we are loading from Google Fonts (FIXME don't load from google) + fontSrc: "font-src 'self' data: https:;", // Disallow submitting any forms formAction: "form-action 'none';", // Disallow framing. frameSrc: "frame-src 'none';", - imgSrc: !IS_PROD - ? // Only allow HTTPS for images. Token provider logos must be https:// - // Allow `data:` `blob:`. - "img-src 'self' 'unsafe-inline' file: data: blob: https:;" - : // Only allow HTTPS for images. Token provider logos must be https:// - // Allow `data:` `blob:`. - "img-src 'unsafe-inline' file: data: blob: https:;", // Additionally used in Parity-JS Shell `'self'` + // Restrict images to only images from known sources + imgSrc: "img-src 'self' data:;", // Disallow manifests. manifestSrc: "manifest-src 'none';", // Disallow media. mediaSrc: "media-src 'none';", // Disallow fonts and `` objects objectSrc: "object-src 'none';", - // Disallow prefetching. - prefetchSrc: "prefetch-src 'none';", - scriptSrc: !IS_PROD - ? // Only allow `http:` and `unsafe-eval` in dev mode (required by create-react-app) - "script-src 'self' file: http: blob: 'unsafe-inline' 'unsafe-eval';" - : "script-src file: 'unsafe-inline';", - styleSrc: !IS_PROD - ? "style-src 'self' 'unsafe-inline' file: blob:;" // Additionally used in Parity-JS Shell `data: https:` - : "style-src unsafe-inline' file: blob:;", // Additionally used in Parity-JS Shell `data: https:` - // Allow `blob:` for camera access (worker) - workerSrc: 'worker-src blob:;' // Additionally used in Parity-JS Shell `'self' https:` + // Disallow unknown scripts + scriptSrc: "script-src 'self' 'unsafe-inline';", + // Disallow stylesheets, we allow https because we are loading from Google Fonts (FIXME don't load from google) + styleSrc: "style-src 'self' 'unsafe-inline' https:;", + // Disallow workers, allow `blob:` for camera access if needed + workerSrc: "worker-src 'none';" }; -/* eslint-enable */ -const CSP = Object.values(CSP_CONFIG).join(' '); - -export { CSP }; +export const CSP = Object.values(CSP_CONFIG).join(' '); diff --git a/packages/light-apps/public/index.html b/packages/light-apps/public/index.html index 3f57904a3..d9f45b8b5 100644 --- a/packages/light-apps/public/index.html +++ b/packages/light-apps/public/index.html @@ -1,16 +1,34 @@ - - - - - - + + - - - Substrate Light UI - - - -
+ Substrate Light UI + + + + +
+ + -