Browse Source

fix #589: use DOM-based CSP directive (idea from 6e80d3f130)

pull/2/head
Raymond Hill 6 years ago
parent
commit
f075f96c58
No known key found for this signature in database GPG Key ID: 25E1490B761470C2
  1. 62
      src/js/contentscript-no-inline-script.js
  2. 62
      src/js/contentscript-no-workers.js
  3. 42
      src/js/matrix.js
  4. 9
      src/js/messaging.js
  5. 93
      src/js/traffic.js

62
src/js/contentscript-no-inline-script.js

@ -0,0 +1,62 @@
/*******************************************************************************
uMatrix - a Chromium browser extension to black/white list requests.
Copyright (C) 2018 Raymond Hill
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see {http://www.gnu.org/licenses/}.
Home: https://github.com/gorhill/uMatrix
*/
'use strict';
// The idea of using <meta http-equiv> to enforce CSP directive has been
// borrowed from NoScript:
// https://github.com/hackademix/noscript/commit/6e80d3f130773fc9a9123c5c4c2e97d63e90fa2a
(function() {
let html = document.documentElement;
if ( html instanceof HTMLElement === false ) { return; }
let meta;
try {
meta = document.createElement('meta');
} catch(ex) {
}
if ( meta === undefined ) { return; }
meta.setAttribute('http-equiv', 'content-security-policy');
meta.setAttribute('content', "script-src 'unsafe-eval' blob: *");
// https://html.spec.whatwg.org/multipage/semantics.html#attr-meta-http-equiv-content-security-policy
//
// Only a head element can be parent:
// > If the meta element is not a child of a head element, return.
//
// The CSP directive is enforced as soon as the meta tag is inserted:
// > Enforce the policy policy.
let head = document.head,
parent = head;
if ( parent === null ) {
parent = document.createElement('head');
html.appendChild(parent);
}
parent.appendChild(meta);
// Restore DOM to its original state.
if ( head === null ) {
html.removeChild(parent);
} else {
parent.removeChild(meta);
}
})();

62
src/js/contentscript-no-workers.js

@ -0,0 +1,62 @@
/*******************************************************************************
uMatrix - a Chromium browser extension to black/white list requests.
Copyright (C) 2018 Raymond Hill
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see {http://www.gnu.org/licenses/}.
Home: https://github.com/gorhill/uMatrix
*/
'use strict';
// The idea of using <meta http-equiv> to enforce CSP directive has been
// borrowed from NoScript:
// https://github.com/hackademix/noscript/commit/6e80d3f130773fc9a9123c5c4c2e97d63e90fa2a
(function() {
let html = document.documentElement;
if ( html instanceof HTMLElement === false ) { return; }
let meta;
try {
meta = document.createElement('meta');
} catch(ex) {
}
if ( meta === undefined ) { return; }
meta.setAttribute('http-equiv', 'content-security-policy');
meta.setAttribute('content', "worker-src 'none'");
// https://html.spec.whatwg.org/multipage/semantics.html#attr-meta-http-equiv-content-security-policy
//
// Only a head element can be parent:
// > If the meta element is not a child of a head element, return.
//
// The CSP directive is enforced as soon as the meta tag is inserted:
// > Enforce the policy policy.
let head = document.head,
parent = head;
if ( parent === null ) {
parent = document.createElement('head');
html.appendChild(parent);
}
parent.appendChild(meta);
// Restore DOM to its original state.
if ( head === null ) {
html.removeChild(parent);
} else {
parent.removeChild(meta);
}
})();

42
src/js/matrix.js

@ -1,7 +1,7 @@
/*******************************************************************************
uMatrix - a Chromium browser extension to black/white list requests.
Copyright (C) 2014-2018 Raymond Hill
uMatrix - a browser extension to black/white list requests.
Copyright (C) 2014-present Raymond Hill
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -199,6 +199,30 @@ Matrix.prototype.reset = function() {
this.rules = new Map();
this.rootValue = Matrix.RedIndirect;
this.modifiedTime = 0;
if ( this.modifyEventTimer !== undefined ) {
clearTimeout(this.modifyEventTimer);
}
this.modifyEventTimer = undefined;
this.modified();
};
/******************************************************************************/
Matrix.prototype.modified = function() {
this.modifiedTime = Date.now();
if ( this.modifyEventTimer !== undefined ) { return; }
this.modifyEventTimer = vAPI.setTimeout(
( ) => {
this.modifyEventTimer = undefined;
window.dispatchEvent(
new CustomEvent(
'matrixRulesetChange',
{ detail: this }
)
);
},
149
);
};
/******************************************************************************/
@ -242,7 +266,7 @@ Matrix.prototype.assign = function(other) {
for ( entry of other.switches ) {
this.switches.set(entry[0], entry[1]);
}
this.modifiedTime = other.modifiedTime;
this.modified();
return this;
};
@ -268,7 +292,7 @@ Matrix.prototype.setSwitch = function(switchName, srcHostname, newVal) {
} else {
this.switches.set(srcHostname, bits);
}
this.modifiedTime = Date.now();
this.modified();
return true;
};
@ -290,7 +314,7 @@ Matrix.prototype.setCell = function(srcHostname, desHostname, type, state) {
} else {
this.rules.set(k, newBitmap);
}
this.modifiedTime = Date.now();
this.modified();
return true;
};
@ -531,7 +555,7 @@ Matrix.prototype.setSwitchZ = function(switchName, srcHostname, newState) {
} else {
this.switches.set(srcHostname, bits);
}
this.modifiedTime = Date.now();
this.modified();
state = this.evaluateSwitchZ(switchName, srcHostname);
if ( state === newState ) {
return true;
@ -645,7 +669,7 @@ Matrix.prototype.fromArray = function(lines, append) {
if ( append !== true ) {
this.assign(matrix);
}
this.modifiedTime = Date.now();
this.modified();
};
Matrix.prototype.toArray = function() {
@ -707,7 +731,7 @@ Matrix.prototype.fromString = function(text, append) {
this.assign(matrix);
}
this.modifiedTime = Date.now();
this.modified();
};
Matrix.prototype.toString = function() {
@ -750,7 +774,7 @@ Matrix.prototype.fromSelfie = function(selfie) {
if ( selfie.version !== selfieVersion ) { return false; }
this.switches = new Map(selfie.switches);
this.rules = new Map(selfie.rules);
this.modifiedTime = Date.now();
this.modified();
return true;
};

9
src/js/messaging.js

@ -1,7 +1,7 @@
/*******************************************************************************
uMatrix - a browser extension to black/white list requests.
Copyright (C) 2014-2018 Raymond Hill
Copyright (C) 2014-present Raymond Hill
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -229,6 +229,13 @@ var matrixSnapshot = function(pageStore, details) {
let µmuri = µm.URI;
let anyIndex = headerIndices.get('*');
// Ensure that the current scope is also reported in the matrix. This may
// not be the case for documents which are fetched without going through
// our webRequest listener (ex. `file:`).
if ( pageStore.hostnameTypeCells.has(r.hostname + ' doc') === false ) {
pageStore.hostnameTypeCells.set(r.hostname + ' doc', new Set([ 0 ]));
}
for ( let entry of pageStore.hostnameTypeCells ) {
let pos = entry[0].indexOf(' ');
let reqHostname = entry[0].slice(0, pos);

93
src/js/traffic.js

@ -1,7 +1,7 @@
/*******************************************************************************
uMatrix - a browser extension to black/white list requests.
Copyright (C) 2014-2018 Raymond Hill
Copyright (C) 2014-present Raymond Hill
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -483,6 +483,97 @@ vAPI.net.onHeadersReceived = {
callback: onHeadersReceived
};
/*******************************************************************************
Use a `http-equiv` `meta` tag to enforce CSP directives for documents
which protocol is `file:` (which do not cause our webRequest.onHeadersReceived
handler to be called).
Idea borrowed from NoScript:
https://github.com/hackademix/noscript/commit/6e80d3f130773fc9a9123c5c4c2e97d63e90fa2a
**/
(function() {
if (
typeof self.browser !== 'object' ||
typeof browser.contentScripts !== 'object'
) {
return;
}
let csRules = [
{
name: 'script',
file: '/js/contentscript-no-inline-script.js',
pending: undefined,
registered: undefined,
mustRegister: false
},
];
let csSwitches = [
{
name: 'no-workers',
file: '/js/contentscript-no-workers.js',
pending: undefined,
registered: undefined,
mustRegister: false
},
];
let register = function(entry) {
if ( entry.pending !== undefined ) { return; }
entry.pending = browser.contentScripts.register({
js: [ { file: entry.file } ],
matches: [ 'file:///*' ],
runAt: 'document_start'
}).then(
result => {
if ( entry.mustRegister ) {
entry.registered = result;
}
entry.pending = undefined;
},
( ) => {
entry.registered = undefined;
entry.pending = undefined;
}
);
};
let unregister = function(entry) {
if ( entry.registered === undefined ) { return; }
entry.registered.unregister();
entry.registered = undefined;
};
let handler = function(ev) {
let matrix = ev && ev.detail;
if ( matrix !== µMatrix.tMatrix ) { return; }
for ( let cs of csRules ) {
cs.mustRegister = matrix.mustBlock('file-scheme', 'file-scheme', cs.name);
if ( cs.mustRegister === (cs.registered !== undefined) ) { continue; }
if ( cs.mustRegister ) {
register(cs);
} else {
unregister(cs);
}
}
for ( let cs of csSwitches ) {
cs.mustRegister = matrix.evaluateSwitchZ(cs.name, 'file-scheme');
if ( cs.mustRegister === (cs.registered !== undefined) ) { continue; }
if ( cs.mustRegister ) {
register(cs);
} else {
unregister(cs);
}
}
};
window.addEventListener('matrixRulesetChange', handler);
})();
/******************************************************************************/
var start = function() {

Loading…
Cancel
Save