diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/misc.js | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/common/misc.js b/common/misc.js index 7158d32..3c7dc46 100644 --- a/common/misc.js +++ b/common/misc.js @@ -155,6 +155,59 @@ function sign_policy(policy, now, hours_offset) { return gen_unique(time + policy); } +/* Parse a CSP header */ +function parse_csp(csp) { + let directive, directive_array; + let directives = {}; + for (directive of csp.split(';')) { + directive = directive.trim(); + if (directive === '') + continue; + + directive_array = directive.split(/\s+/); + directive = directive_array.shift(); + /* The "true" case should never occur; nevertheless... */ + directives[directive] = directive in directives ? + directives[directive].concat(directive_array) : + directive_array; + } + return directives; +} + +/* Make CSP headers do our bidding, not interfere */ +function sanitize_csp_header(header, rule, block) +{ + const csp = parse_csp(header.value); + + if (block) { + /* No snitching */ + delete csp['report-to']; + delete csp['report-uri']; + + delete csp['script-src']; + delete csp['script-src-elem']; + + csp['script-src-attr'] = ["'none'"]; + csp['prefetch-src'] = ["'none'"]; + } + + if ('script-src' in csp) + csp['script-src'].push(rule); + else + csp['script-src'] = [rule]; + + if ('script-src-elem' in csp) + csp['script-src-elem'].push(rule); + else + csp['script-src-elem'] = [rule]; + + const new_policy = Object.entries(csp).map( + i => `${i[0]} ${i[1].join(' ')};` + ); + + return {name: header.name, value: new_policy.join('')}; +} + /* Regexes and objest to use as/in schemas for parse_json_with_schema(). */ const nonempty_string_matcher = /.+/; @@ -178,6 +231,7 @@ const matchers = { * EXPORT nice_name * EXPORT open_in_settings * EXPORT is_privileged_url + * EXPORT sanitize_csp_header * EXPORT matchers * EXPORTS_END */ |