-
Notifications
You must be signed in to change notification settings - Fork 0
/
deterministic.py
50 lines (44 loc) · 1.75 KB
/
deterministic.py
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
import re
import hashlib
import base64
import time
import os
file_path = os.path.dirname(os.path.realpath(__file__))
class Deterministic:
def load(self, loader):
with open(file_path + '/deterministic.js', 'r') as file:
self.js = file.read().replace('`WPR_TIME_SEED_TIMESTAMP`', str(int(time.time()*1000)))
sha256 = hashlib.sha256()
sha256.update(self.js.encode('utf-8'))
self.js_csp = '; script-src \'sha256-' + base64.b64encode(sha256.digest()).decode('utf-8') + '\''
def response(self, flow):
response = flow.response
if not response:
return
if not response.content:
return
if 'text/html' not in response.headers.get('content-type'):
return
if b'<head' not in response.content:
return
headers = flow.response.headers
for csp_header in ['content-security-policy', 'content-security-policy-report-only']:
if not headers.get(csp_header):
continue
del headers[csp_header]
# This breaks if a server responds with two CSP headers. We overwrite all but the last one.
# and for that reason, CSP headers are out.
# headers['X-Original-' + csp_header] = headers[csp_header]
# headers[csp_header] = re.sub(
# '(;\s*)?(script-src|$)',
# self.js_csp,
# headers[csp_header],
# 1
# )
script = '<script type="text/javascript">' + self.js + '</script>'
response.content = re.sub(
b'<head[^>]*>',
lambda match: match.group(0) + script.encode('utf-8'),
response.content
)
addons = [Deterministic()]