Skip to content
This repository has been archived by the owner on Jul 21, 2021. It is now read-only.

Commit

Permalink
fix #589: use DOM-based CSP directive (idea from hackademix/noscript@6…
Browse files Browse the repository at this point in the history
  • Loading branch information
gorhill committed Sep 17, 2018
1 parent 7f3122c commit f075f96
Show file tree
Hide file tree
Showing 5 changed files with 257 additions and 11 deletions.
62 changes: 62 additions & 0 deletions src/js/contentscript-no-inline-script.js
Original file line number Diff line number Diff line change
@@ -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 changes: 62 additions & 0 deletions src/js/contentscript-no-workers.js
Original file line number Diff line number Diff line change
@@ -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 changes: 33 additions & 9 deletions src/js/matrix.js
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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
);
};

/******************************************************************************/
Expand Down Expand Up @@ -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;
};

Expand All @@ -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;
};

Expand All @@ -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;
};

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -707,7 +731,7 @@ Matrix.prototype.fromString = function(text, append) {
this.assign(matrix);
}

this.modifiedTime = Date.now();
this.modified();
};

Matrix.prototype.toString = function() {
Expand Down Expand Up @@ -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;
};

Expand Down
9 changes: 8 additions & 1 deletion src/js/messaging.js
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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);
Expand Down
93 changes: 92 additions & 1 deletion src/js/traffic.js
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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() {
Expand Down

0 comments on commit f075f96

Please sign in to comment.