Skip to content

Commit

Permalink
SECURE_DEFAULT_HEADERS setting instead of several
Browse files Browse the repository at this point in the history
  • Loading branch information
davegaeddert committed Sep 27, 2024
1 parent 86e6dfa commit 80c6bd8
Show file tree
Hide file tree
Showing 11 changed files with 15 additions and 261 deletions.
1 change: 0 additions & 1 deletion plain-auth/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ MIDDLEWARE = [
"plain.middleware.common.CommonMiddleware",
"plain.csrf.middleware.CsrfViewMiddleware",
"plain.auth.middleware.AuthenticationMiddleware", # <--
"plain.middleware.clickjacking.XFrameOptionsMiddleware",
]

AUTH_USER_MODEL = "users.User"
Expand Down
1 change: 0 additions & 1 deletion plain-auth/plain/auth/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ MIDDLEWARE = [
"plain.middleware.common.CommonMiddleware",
"plain.csrf.middleware.CsrfViewMiddleware",
"plain.auth.middleware.AuthenticationMiddleware", # <--
"plain.middleware.clickjacking.XFrameOptionsMiddleware",
]

AUTH_USER_MODEL = "users.User"
Expand Down
1 change: 0 additions & 1 deletion plain-importmap/test_project/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
"plain.middleware.common.CommonMiddleware",
"plain.csrf.middleware.CsrfViewMiddleware",
"plain.auth.middleware.AuthenticationMiddleware",
"plain.middleware.clickjacking.XFrameOptionsMiddleware",
]

ROOT_URLCONF = "app.urls"
Expand Down
1 change: 0 additions & 1 deletion plain-staff/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ MIDDLEWARE = [
"plain.middleware.common.CommonMiddleware",
"plain.csrf.middleware.CsrfViewMiddleware",
"plain.auth.middleware.AuthenticationMiddleware",
"plain.middleware.clickjacking.XFrameOptionsMiddleware",
"plain.staff.querystats.QueryStatsMiddleware",
# Put additional middleware below querystats
Expand Down
1 change: 0 additions & 1 deletion plain-staff/plain/staff/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ MIDDLEWARE = [
"plain.middleware.common.CommonMiddleware",
"plain.csrf.middleware.CsrfViewMiddleware",
"plain.auth.middleware.AuthenticationMiddleware",
"plain.middleware.clickjacking.XFrameOptionsMiddleware",
"plain.staff.querystats.QueryStatsMiddleware",
# Put additional middleware below querystats
Expand Down
1 change: 0 additions & 1 deletion plain-staff/plain/staff/querystats/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ MIDDLEWARE = [
"plain.middleware.common.CommonMiddleware",
"plain.csrf.middleware.CsrfViewMiddleware",
"plain.auth.middleware.AuthenticationMiddleware",
"plain.middleware.clickjacking.XFrameOptionsMiddleware",

"plain.staff.querystats.QueryStatsMiddleware",
# Put additional middleware below querystats
Expand Down
52 changes: 0 additions & 52 deletions plain/plain/middleware/clickjacking.py

This file was deleted.

41 changes: 4 additions & 37 deletions plain/plain/middleware/security.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,11 @@
class SecurityMiddleware:
def __init__(self, get_response):
self.get_response = get_response
self.sts_seconds = settings.SECURE_HSTS_SECONDS
self.sts_include_subdomains = settings.SECURE_HSTS_INCLUDE_SUBDOMAINS
self.sts_preload = settings.SECURE_HSTS_PRELOAD
self.content_type_nosniff = settings.SECURE_CONTENT_TYPE_NOSNIFF
self.redirect = settings.SECURE_SSL_REDIRECT
self.redirect_host = settings.SECURE_SSL_HOST
self.redirect_exempt = [re.compile(r) for r in settings.SECURE_REDIRECT_EXEMPT]
self.referrer_policy = settings.SECURE_REFERRER_POLICY
self.cross_origin_opener_policy = settings.SECURE_CROSS_ORIGIN_OPENER_POLICY

self.default_headers = settings.SECURE_DEFAULT_HEADERS

def __call__(self, request):
path = request.path.lstrip("/")
Expand All @@ -29,36 +25,7 @@ def __call__(self, request):

response = self.get_response(request)

if (
self.sts_seconds
and request.is_secure()
and "Strict-Transport-Security" not in response
):
sts_header = "max-age=%s" % self.sts_seconds
if self.sts_include_subdomains:
sts_header += "; includeSubDomains"
if self.sts_preload:
sts_header += "; preload"
response.headers["Strict-Transport-Security"] = sts_header

if self.content_type_nosniff:
response.headers.setdefault("X-Content-Type-Options", "nosniff")

if self.referrer_policy:
# Support a comma-separated string or iterable of values to allow
# fallback.
response.headers.setdefault(
"Referrer-Policy",
",".join(
[v.strip() for v in self.referrer_policy.split(",")]
if isinstance(self.referrer_policy, str)
else self.referrer_policy
),
)
for header, value in self.default_headers.items():
response.headers.setdefault(header, value)

if self.cross_origin_opener_policy:
response.setdefault(
"Cross-Origin-Opener-Policy",
self.cross_origin_opener_policy,
)
return response
156 changes: 1 addition & 155 deletions plain/plain/preflight/security/base.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,7 @@
from plain.exceptions import ImproperlyConfigured
from plain.runtime import settings

from .. import Error, Warning, register

CROSS_ORIGIN_OPENER_POLICY_VALUES = {
"same-origin",
"same-origin-allow-popups",
"unsafe-none",
}
REFERRER_POLICY_VALUES = {
"no-referrer",
"no-referrer-when-downgrade",
"origin",
"origin-when-cross-origin",
"same-origin",
"strict-origin",
"strict-origin-when-cross-origin",
"unsafe-url",
}
from .. import Warning, register

SECRET_KEY_INSECURE_PREFIX = "plain-insecure-"
SECRET_KEY_MIN_LENGTH = 50
Expand All @@ -41,43 +25,6 @@
id="security.W001",
)

W002 = Warning(
"You do not have "
"'plain.middleware.clickjacking.XFrameOptionsMiddleware' in your "
"MIDDLEWARE, so your pages will not be served with an "
"'x-frame-options' header. Unless there is a good reason for your "
"site to be served in a frame, you should consider enabling this "
"header to help prevent clickjacking attacks.",
id="security.W002",
)

W004 = Warning(
"You have not set a value for the SECURE_HSTS_SECONDS setting. "
"If your entire site is served only over SSL, you may want to consider "
"setting a value and enabling HTTP Strict Transport Security. "
"Be sure to read the documentation first; enabling HSTS carelessly "
"can cause serious, irreversible problems.",
id="security.W004",
)

W005 = Warning(
"You have not set the SECURE_HSTS_INCLUDE_SUBDOMAINS setting to True. "
"Without this, your site is potentially vulnerable to attack "
"via an insecure connection to a subdomain. Only set this to True if "
"you are certain that all subdomains of your domain should be served "
"exclusively via SSL.",
id="security.W005",
)

W006 = Warning(
"Your SECURE_CONTENT_TYPE_NOSNIFF setting is not set to True, "
"so your pages will not be served with an "
"'X-Content-Type-Options: nosniff' header. "
"You should consider enabling this header to prevent the "
"browser from identifying content types incorrectly.",
id="security.W006",
)

W008 = Warning(
"Your SECURE_SSL_REDIRECT setting is not set to True. "
"Unless your site should be available over both SSL and non-SSL "
Expand All @@ -102,93 +49,19 @@
id="security.W020",
)

W021 = Warning(
"You have not set the SECURE_HSTS_PRELOAD setting to True. Without this, "
"your site cannot be submitted to the browser preload list.",
id="security.W021",
)

W022 = Warning(
"You have not set the SECURE_REFERRER_POLICY setting. Without this, your "
"site will not send a Referrer-Policy header. You should consider "
"enabling this header to protect user privacy.",
id="security.W022",
)

E023 = Error(
"You have set the SECURE_REFERRER_POLICY setting to an invalid value.",
hint="Valid values are: {}.".format(", ".join(sorted(REFERRER_POLICY_VALUES))),
id="security.E023",
)

E024 = Error(
"You have set the SECURE_CROSS_ORIGIN_OPENER_POLICY setting to an invalid "
"value.",
hint="Valid values are: {}.".format(
", ".join(sorted(CROSS_ORIGIN_OPENER_POLICY_VALUES)),
),
id="security.E024",
)

W025 = Warning(SECRET_KEY_WARNING_MSG, id="security.W025")


def _security_middleware():
return "plain.middleware.security.SecurityMiddleware" in settings.MIDDLEWARE


def _xframe_middleware():
return (
"plain.middleware.clickjacking.XFrameOptionsMiddleware" in settings.MIDDLEWARE
)


@register(deploy=True)
def check_security_middleware(package_configs, **kwargs):
passed_check = _security_middleware()
return [] if passed_check else [W001]


@register(deploy=True)
def check_xframe_options_middleware(package_configs, **kwargs):
passed_check = _xframe_middleware()
return [] if passed_check else [W002]


@register(deploy=True)
def check_sts(package_configs, **kwargs):
passed_check = not _security_middleware() or settings.SECURE_HSTS_SECONDS
return [] if passed_check else [W004]


@register(deploy=True)
def check_sts_include_subdomains(package_configs, **kwargs):
passed_check = (
not _security_middleware()
or not settings.SECURE_HSTS_SECONDS
or settings.SECURE_HSTS_INCLUDE_SUBDOMAINS is True
)
return [] if passed_check else [W005]


@register(deploy=True)
def check_sts_preload(package_configs, **kwargs):
passed_check = (
not _security_middleware()
or not settings.SECURE_HSTS_SECONDS
or settings.SECURE_HSTS_PRELOAD is True
)
return [] if passed_check else [W021]


@register(deploy=True)
def check_content_type_nosniff(package_configs, **kwargs):
passed_check = (
not _security_middleware() or settings.SECURE_CONTENT_TYPE_NOSNIFF is True
)
return [] if passed_check else [W006]


@register(deploy=True)
def check_ssl_redirect(package_configs, **kwargs):
passed_check = not _security_middleware() or settings.SECURE_SSL_REDIRECT is True
Expand Down Expand Up @@ -239,30 +112,3 @@ def check_debug(package_configs, **kwargs):
@register(deploy=True)
def check_allowed_hosts(package_configs, **kwargs):
return [] if settings.ALLOWED_HOSTS else [W020]


@register(deploy=True)
def check_referrer_policy(package_configs, **kwargs):
if _security_middleware():
if settings.SECURE_REFERRER_POLICY is None:
return [W022]
# Support a comma-separated string or iterable of values to allow fallback.
if isinstance(settings.SECURE_REFERRER_POLICY, str):
values = {v.strip() for v in settings.SECURE_REFERRER_POLICY.split(",")}
else:
values = set(settings.SECURE_REFERRER_POLICY)
if not values <= REFERRER_POLICY_VALUES:
return [E023]
return []


@register(deploy=True)
def check_cross_origin_opener_policy(package_configs, **kwargs):
if (
_security_middleware()
and settings.SECURE_CROSS_ORIGIN_OPENER_POLICY is not None
and settings.SECURE_CROSS_ORIGIN_OPENER_POLICY
not in CROSS_ORIGIN_OPENER_POLICY_VALUES
):
return [E024]
return []
1 change: 0 additions & 1 deletion plain/plain/runtime/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ MIDDLEWARE = [
"plain.middleware.common.CommonMiddleware",
"plain.csrf.middleware.CsrfViewMiddleware",
"plain.auth.middleware.AuthenticationMiddleware",
"plain.middleware.clickjacking.XFrameOptionsMiddleware",
]

if DEBUG:
Expand Down
Loading

0 comments on commit 80c6bd8

Please sign in to comment.