| 31 | |
| 32 | |
| 33 | def response(flow: http.HTTPFlow) -> None: |
| 34 | assert flow.response |
| 35 | flow.response.headers.pop("Strict-Transport-Security", None) |
| 36 | flow.response.headers.pop("Public-Key-Pins", None) |
| 37 | |
| 38 | # strip links in response body |
| 39 | flow.response.content = flow.response.content.replace(b"https://", b"http://") |
| 40 | |
| 41 | # strip meta tag upgrade-insecure-requests in response body |
| 42 | csp_meta_tag_pattern = rb'<meta.*http-equiv=["\']Content-Security-Policy[\'"].*upgrade-insecure-requests.*?>' |
| 43 | flow.response.content = re.sub( |
| 44 | csp_meta_tag_pattern, b"", flow.response.content, flags=re.IGNORECASE |
| 45 | ) |
| 46 | |
| 47 | # strip links in 'Location' header |
| 48 | if flow.response.headers.get("Location", "").startswith("https://"): |
| 49 | location = flow.response.headers["Location"] |
| 50 | hostname = urllib.parse.urlparse(location).hostname |
| 51 | if hostname: |
| 52 | secure_hosts.add(hostname) |
| 53 | flow.response.headers["Location"] = location.replace("https://", "http://", 1) |
| 54 | |
| 55 | # strip upgrade-insecure-requests in Content-Security-Policy header |
| 56 | csp_header = flow.response.headers.get("Content-Security-Policy", "") |
| 57 | if re.search("upgrade-insecure-requests", csp_header, flags=re.IGNORECASE): |
| 58 | csp = flow.response.headers["Content-Security-Policy"] |
| 59 | new_header = re.sub( |
| 60 | r"upgrade-insecure-requests[;\s]*", "", csp, flags=re.IGNORECASE |
| 61 | ) |
| 62 | flow.response.headers["Content-Security-Policy"] = new_header |
| 63 | |
| 64 | # strip secure flag from 'Set-Cookie' headers |
| 65 | cookies = flow.response.headers.get_all("Set-Cookie") |
| 66 | cookies = [re.sub(r";\s*secure\s*", "", s) for s in cookies] |
| 67 | flow.response.headers.set_all("Set-Cookie", cookies) |