зеркало из https://github.com/mozilla/django-csp.git
94 строки
3.0 KiB
Python
94 строки
3.0 KiB
Python
from __future__ import annotations
|
|
|
|
import pprint
|
|
from collections.abc import Sequence
|
|
from typing import TYPE_CHECKING, Any
|
|
|
|
from django.conf import settings
|
|
from django.core.checks import Error
|
|
|
|
from csp.constants import NONCE
|
|
|
|
if TYPE_CHECKING:
|
|
from django.apps.config import AppConfig
|
|
|
|
|
|
OUTDATED_SETTINGS = [
|
|
"CSP_CHILD_SRC",
|
|
"CSP_CONNECT_SRC",
|
|
"CSP_DEFAULT_SRC",
|
|
"CSP_SCRIPT_SRC",
|
|
"CSP_SCRIPT_SRC_ATTR",
|
|
"CSP_SCRIPT_SRC_ELEM",
|
|
"CSP_OBJECT_SRC",
|
|
"CSP_STYLE_SRC",
|
|
"CSP_STYLE_SRC_ATTR",
|
|
"CSP_STYLE_SRC_ELEM",
|
|
"CSP_FONT_SRC",
|
|
"CSP_FRAME_SRC",
|
|
"CSP_IMG_SRC",
|
|
"CSP_MANIFEST_SRC",
|
|
"CSP_MEDIA_SRC",
|
|
"CSP_PREFETCH_SRC",
|
|
"CSP_WORKER_SRC",
|
|
"CSP_BASE_URI",
|
|
"CSP_PLUGIN_TYPES",
|
|
"CSP_SANDBOX",
|
|
"CSP_FORM_ACTION",
|
|
"CSP_FRAME_ANCESTORS",
|
|
"CSP_NAVIGATE_TO",
|
|
"CSP_REQUIRE_SRI_FOR",
|
|
"CSP_REQUIRE_TRUSTED_TYPES_FOR",
|
|
"CSP_TRUSTED_TYPES",
|
|
"CSP_UPGRADE_INSECURE_REQUESTS",
|
|
"CSP_BLOCK_ALL_MIXED_CONTENT",
|
|
"CSP_REPORT_URI",
|
|
"CSP_REPORT_TO",
|
|
]
|
|
|
|
|
|
def migrate_settings() -> tuple[dict[str, Any], bool]:
|
|
# This function is used to migrate settings from the old format to the new format.
|
|
config: dict[str, Any] = {
|
|
"DIRECTIVES": {},
|
|
}
|
|
|
|
REPORT_ONLY = getattr(settings, "CSP_REPORT_ONLY", False)
|
|
|
|
_EXCLUDE_URL_PREFIXES = getattr(settings, "CSP_EXCLUDE_URL_PREFIXES", None)
|
|
if _EXCLUDE_URL_PREFIXES is not None:
|
|
config["EXCLUDE_URL_PREFIXES"] = _EXCLUDE_URL_PREFIXES
|
|
|
|
_REPORT_PERCENTAGE = getattr(settings, "CSP_REPORT_PERCENTAGE", None)
|
|
if _REPORT_PERCENTAGE is not None:
|
|
config["REPORT_PERCENTAGE"] = _REPORT_PERCENTAGE * 100
|
|
|
|
include_nonce_in = getattr(settings, "CSP_INCLUDE_NONCE_IN", [])
|
|
|
|
for setting in OUTDATED_SETTINGS:
|
|
if hasattr(settings, setting):
|
|
directive = setting[4:].replace("_", "-").lower()
|
|
value = getattr(settings, setting)
|
|
if value:
|
|
config["DIRECTIVES"][directive] = value
|
|
if directive in include_nonce_in:
|
|
config["DIRECTIVES"][directive].append(NONCE)
|
|
|
|
return config, REPORT_ONLY
|
|
|
|
|
|
def check_django_csp_lt_4_0(app_configs: Sequence[AppConfig] | None, **kwargs: Any) -> list[Error]:
|
|
check_settings = OUTDATED_SETTINGS + ["CSP_REPORT_ONLY", "CSP_EXCLUDE_URL_PREFIXES", "CSP_REPORT_PERCENTAGE"]
|
|
if any(hasattr(settings, setting) for setting in check_settings):
|
|
# Try to build the new config.
|
|
config, REPORT_ONLY = migrate_settings()
|
|
warning = (
|
|
"You are using django-csp < 4.0 settings. Please update your settings to use the new format.\n"
|
|
"See https://django-csp.readthedocs.io/en/latest/migration-guide.html for more information.\n\n"
|
|
"We have attempted to build the new CSP config for you based on your current settings:\n\n"
|
|
f"CONTENT_SECURITY_POLICY{'_REPORT_ONLY' if REPORT_ONLY else ''} = " + pprint.pformat(config, sort_dicts=True)
|
|
)
|
|
return [Error(warning, id="csp.E001")]
|
|
|
|
return []
|