2024-07-01 20:16:09 +03:00
|
|
|
from __future__ import annotations
|
2024-07-01 23:49:27 +03:00
|
|
|
|
2018-04-06 16:47:28 +03:00
|
|
|
import random
|
2024-07-01 23:49:27 +03:00
|
|
|
from typing import TYPE_CHECKING
|
2018-04-06 16:47:28 +03:00
|
|
|
|
|
|
|
from django.conf import settings
|
|
|
|
|
2024-07-10 14:26:32 +03:00
|
|
|
from csp.middleware import CSPMiddleware, PolicyParts
|
2018-04-06 16:47:28 +03:00
|
|
|
|
2024-07-01 20:16:09 +03:00
|
|
|
if TYPE_CHECKING:
|
|
|
|
from django.http import HttpRequest, HttpResponseBase
|
|
|
|
|
2018-04-06 16:47:28 +03:00
|
|
|
|
|
|
|
class RateLimitedCSPMiddleware(CSPMiddleware):
|
|
|
|
"""A CSP middleware that rate-limits the number of violation reports sent
|
|
|
|
to report-uri by excluding it from some requests."""
|
|
|
|
|
2024-07-10 14:26:32 +03:00
|
|
|
def get_policy_parts(self, request: HttpRequest, response: HttpResponseBase, report_only: bool = False) -> PolicyParts:
|
|
|
|
policy_parts = super().get_policy_parts(request, response, report_only)
|
2024-05-01 22:58:56 +03:00
|
|
|
|
2024-07-10 14:26:32 +03:00
|
|
|
csp_setting_name = "CONTENT_SECURITY_POLICY_REPORT_ONLY" if report_only else "CONTENT_SECURITY_POLICY"
|
|
|
|
policy = getattr(settings, csp_setting_name, None)
|
2024-05-01 22:58:56 +03:00
|
|
|
if policy is None:
|
2024-07-10 14:26:32 +03:00
|
|
|
return policy_parts
|
2024-05-01 22:58:56 +03:00
|
|
|
|
2024-09-11 03:41:44 +03:00
|
|
|
# `random.random` returns a value in the range [0.0, 1.0) so all values will be < 100.0.
|
|
|
|
remove_report = random.random() * 100 >= policy.get("REPORT_PERCENTAGE", 100)
|
2024-07-10 01:57:41 +03:00
|
|
|
if remove_report:
|
2024-07-10 14:26:32 +03:00
|
|
|
if policy_parts.replace is None:
|
|
|
|
policy_parts.replace = {
|
2024-07-10 01:57:41 +03:00
|
|
|
"report-uri": None,
|
|
|
|
"report-to": None,
|
|
|
|
}
|
2024-07-10 14:26:32 +03:00
|
|
|
else:
|
|
|
|
policy_parts.replace.update(
|
|
|
|
{
|
|
|
|
"report-uri": None,
|
|
|
|
"report-to": None,
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
return policy_parts
|