tightened content security policy to prevent browser extension from adding scripts to KeeWeb

This commit is contained in:
antelle 2021-04-11 11:44:51 +02:00
parent 5f4f007b31
commit dcc477acbc
No known key found for this signature in database
GPG Key ID: 63C9777AAB7C563C
4 changed files with 25 additions and 22 deletions

View File

@ -8,7 +8,7 @@
content=" content="
default-src 'self'; default-src 'self';
font-src data:; font-src data:;
script-src 'self' blob: 'unsafe-eval'; script-src 'self' 'unsafe-eval';
style-src 'self' blob:; style-src 'self' blob:;
connect-src 'self' ws: https:; connect-src 'self' ws: https:;
child-src 'self' blob:; child-src 'self' blob:;

View File

@ -373,25 +373,27 @@ class Plugin extends Model {
}; };
text = `(function(require, module){${text}})(window["${jsVar}"].require,window["${jsVar}"].module);`; text = `(function(require, module){${text}})(window["${jsVar}"].require,window["${jsVar}"].module);`;
const ts = this.logger.ts(); const ts = this.logger.ts();
const blob = new Blob([text], { type: 'text/javascript' });
const objectUrl = URL.createObjectURL(blob); // Note that here we're calling eval to run the plugin code,
const elId = 'plugin-js-' + name; // previously it was loaded as 'blob:' scheme (see the code below), however:
const el = this.createElementInHead('script', elId, { // 1. we need to have eval enabled in our CSP anyway for WASM,
src: objectUrl // see https://github.com/WebAssembly/content-security-policy/issues/7
}); // 2. we would like to prevent Chrome extensions from injecting scripts to our page,
el.addEventListener('load', () => { // which is possible to do if we have 'blob:', but they can't call eval
URL.revokeObjectURL(objectUrl); // Previous implementation with 'blob:' can be found in git, if we ever need to restore it.
setTimeout(() => {
delete global[jsVar]; // eslint-disable-next-line no-eval
if (this.module.exports.uninstall) { eval(text);
this.logger.debug('Plugin script installed', this.logger.ts(ts)); setTimeout(() => {
this.loadPluginSettings(); delete global[jsVar];
resolve(); if (this.module.exports.uninstall) {
} else { this.logger.debug('Plugin script installed', this.logger.ts(ts));
reject('Plugin script installation failed'); this.loadPluginSettings();
} resolve();
}, 0); } else {
}); reject('Plugin script installation failed');
}
}, 0);
} catch (e) { } catch (e) {
this.logger.error('Error installing plugin script', e); this.logger.error('Error installing plugin script', e);
reject(e); reject(e);

View File

@ -41,12 +41,12 @@ module.exports = function (grunt) {
let htmlStr = html.toString('latin1'); let htmlStr = html.toString('latin1');
for (const [type, digests] of Object.entries(hashes)) { for (const [type, digests] of Object.entries(hashes)) {
const cspIndex = htmlStr.indexOf(`${type}-src`); const cspIndex = htmlStr.indexOf(`${type}-src 'self'`);
if (cspIndex < 0) { if (cspIndex < 0) {
grunt.warn(`Not found: ${type}-src`); grunt.warn(`Not found: ${type}-src`);
} }
const digestsList = digests.map((digest) => `'${algo}-${digest}'`).join(' '); const digestsList = digests.map((digest) => `'${algo}-${digest}'`).join(' ');
htmlStr = htmlStr.replace(`${type}-src`, `${type}-src ${digestsList}`); htmlStr = htmlStr.replace(`${type}-src 'self'`, `${type}-src ${digestsList}`);
} }
grunt.log.writeln( grunt.log.writeln(

View File

@ -8,6 +8,7 @@ Release notes
`+` better Touch ID error messages `+` better Touch ID error messages
`-` legacy auto-type removed `-` legacy auto-type removed
`-` fixed a crash after disabling USB devices on Linux `-` fixed a crash after disabling USB devices on Linux
`+` tightened content security policy
##### v1.17.6 (2021-04-09) ##### v1.17.6 (2021-04-09)
`+` team drives support in Google Drive `+` team drives support in Google Drive