aboutsummaryrefslogtreecommitdiffstats
path: root/js/contentscript-start.js
blob: b7d74ba1d4e91bf77ad0654a7b8b600cc0fc87ee (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/*******************************************************************************

    ηMatrix - a browser extension to black/white list requests.
    Copyright (C) 2017-2019 Raymond Hill
    Copyright (C) 2019-2022 Alessio Vanni

    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://gitlab.com/vannilla/ematrix
    uMatrix Home: https://github.com/gorhill/uMatrix
*/

'use strict';

// Injected into content pages
(function () {
    if (typeof vAPI !== 'object') {
	return;
    }

    vAPI.selfWorkerSrcReported = vAPI.selfWorkerSrcReported || false;

    var reGoodWorkerSrc = /(?:frame|worker)-src[^;,]+?'none'/;

    var handler = function(ev) {
        if (ev.isTrusted !== true
	    || ev.originalPolicy.includes('report-uri about:blank') === false) {
            return false;
        }

        // Firefox and Chromium differs in how they fill the
        // 'effectiveDirective' property.
	// ηMatrix: what does Pale Moon/Basilisk do?
        if (ev.effectiveDirective.startsWith('worker-src') === false
	    && ev.effectiveDirective.startsWith('frame-src') === false) {
            return false;
        }

        // Further validate that the policy violation is relevant to ηMatrix:
        // the event still could have been fired as a result of a CSP header
        // not injected by ηMatrix.
        if (reGoodWorkerSrc.test(ev.originalPolicy) === false) {
            return false;
        }

        // We do not want to report internal resources more than once.
        // However, we do want to report external resources each time.
        // TODO: this could eventually lead to duplicated reports for external
        //       resources if another extension uses the same approach as
        //       ηMatrix. Think about what could be done to avoid duplicate
        //       reports.
        if (ev.blockedURI.includes('://') === false) {
            if (vAPI.selfWorkerSrcReported) {
		return true;
	    }
            vAPI.selfWorkerSrcReported = true;
        }

        vAPI.messaging.send('contentscript.js', {
            what: 'securityPolicyViolation',
            directive: 'worker-src',
            blockedURI: ev.blockedURI,
            documentURI: ev.documentURI,
            blocked: ev.disposition === 'enforce'
        });

        return true;
    };

    document.addEventListener('securitypolicyviolation', function (ev) {
        if (!handler(ev)) {
	    return;
	}
        ev.stopPropagation();
        ev.preventDefault();
    }, true);
})();