diff --git a/authentik/brands/tests.py b/authentik/brands/tests.py index e320340565..41d84e82df 100644 --- a/authentik/brands/tests.py +++ b/authentik/brands/tests.py @@ -148,3 +148,14 @@ class TestBrands(APITestCase): "default_locale": "", }, ) + + def test_custom_css(self): + """Test custom_css""" + brand = create_test_brand() + brand.branding_custom_css = """* { + font-family: "Foo bar"; + }""" + brand.save() + res = self.client.get(reverse("authentik_core:if-user")) + self.assertEqual(res.status_code, 200) + self.assertIn(brand.branding_custom_css, res.content.decode()) diff --git a/authentik/brands/utils.py b/authentik/brands/utils.py index 8f8fdf5e9b..3d39410524 100644 --- a/authentik/brands/utils.py +++ b/authentik/brands/utils.py @@ -5,6 +5,8 @@ from typing import Any from django.db.models import F, Q from django.db.models import Value as V from django.http.request import HttpRequest +from django.utils.html import _json_script_escapes +from django.utils.safestring import mark_safe from authentik import get_full_version from authentik.brands.models import Brand @@ -32,8 +34,13 @@ def context_processor(request: HttpRequest) -> dict[str, Any]: """Context Processor that injects brand object into every template""" brand = getattr(request, "brand", DEFAULT_BRAND) tenant = getattr(request, "tenant", Tenant()) + # similarly to `json_script` we escape everything HTML-related, however django + # only directly exposes this as a function that also wraps it in a {% block head %}