Project

General

Profile

« Previous | Next » 

Revision 44e89d8e

Added by koszko almost 2 years ago

simplify CSP handling

All page's CSP rules are now removed when a payload is to be injected. When there is no payload, CSP rules are not modified but only supplemented with Hachette's own.

View differences:

common/misc.js
43 43
    return Uint8toHex(randomData);
44 44
}
45 45

  
46
/* csp rule that blocks all scripts except for those injected by us */
47
function csp_rule(nonce)
46
/* CSP rule that blocks scripts according to policy's needs. */
47
function make_csp_rule(policy)
48 48
{
49
    const rule = `'nonce-${nonce}'`;
50
    return `script-src ${rule}; script-src-elem ${rule}; script-src-attr 'none'; prefetch-src 'none';`;
49
    let rule = "prefetch-src 'none'; script-src-attr 'none';";
50
    const script_src = policy.has_payload ?
51
	  `'nonce-${policy.nonce}'` : "'none'";
52
    rule += ` script-src ${script_src}; script-src-elem ${script_src};`;
53
    return rule;
51 54
}
52 55

  
53 56
/* Check if some HTTP header might define CSP rules. */
54
const csp_header_names = new Set([
55
    "content-security-policy",
56
    "x-webkit-csp",
57
    "x-content-security-policy"
58
]);
59

  
60
const report_only_header_name = "content-security-policy-report-only";
61

  
62
function is_csp_header_name(string, include_report_only)
63
{
64
    string = string && string.toLowerCase().trim() || "";
65

  
66
    return (include_report_only && string === report_only_header_name) ||
67
	csp_header_names.has(string);
68
}
57
const csp_header_regex =
58
      /^\s*(content-security-policy|x-webkit-csp|x-content-security-policy)/i;
69 59

  
70 60
/*
71 61
 * Print item together with type, e.g.
......
111 101
    return directives;
112 102
}
113 103

  
114
/* Make CSP headers do our bidding, not interfere */
115
function sanitize_csp_header(header, policy)
116
{
117
    const rule = `'nonce-${policy.nonce}'`;
118
    const csp = parse_csp(header.value);
119

  
120
    if (!policy.allow) {
121
	/* No snitching */
122
	delete csp['report-to'];
123
	delete csp['report-uri'];
124

  
125
	delete csp['script-src'];
126
	delete csp['script-src-elem'];
127

  
128
	csp['script-src-attr'] = ["'none'"];
129
	csp['prefetch-src'] = ["'none'"];
130
    }
131

  
132
    if ('script-src' in csp)
133
	csp['script-src'].push(rule);
134
    else
135
	csp['script-src'] = [rule];
136

  
137
    if ('script-src-elem' in csp)
138
	csp['script-src-elem'].push(rule);
139
    else
140
	csp['script-src-elem'] = [rule];
141

  
142
    const new_csp = Object.entries(csp).map(
143
	i => `${i[0]} ${i[1].join(' ')};`
144
    );
145

  
146
    return {name: header.name, value: new_csp.join('')};
147
}
148

  
149 104
/* Regexes and objects to use as/in schemas for parse_json_with_schema(). */
150 105
const nonempty_string_matcher = /.+/;
151 106

  
......
161 116
/*
162 117
 * EXPORTS_START
163 118
 * EXPORT gen_nonce
164
 * EXPORT csp_rule
165
 * EXPORT is_csp_header_name
119
 * EXPORT make_csp_rule
120
 * EXPORT csp_header_regex
166 121
 * EXPORT nice_name
167 122
 * EXPORT open_in_settings
168 123
 * EXPORT is_privileged_url
169
 * EXPORT sanitize_csp_header
170 124
 * EXPORT matchers
171 125
 * EXPORTS_END
172 126
 */

Also available in: Unified diff