diff --git a/authentik/events/utils.py b/authentik/events/utils.py index 306897697..b5864e837 100644 --- a/authentik/events/utils.py +++ b/authentik/events/utils.py @@ -30,7 +30,7 @@ def cleanse_item(key: str, value: Any) -> Any: """Cleanse a single item""" if isinstance(value, dict): return cleanse_dict(value) - if isinstance(value, list): + if isinstance(value, (list, tuple, set)): for idx, item in enumerate(value): value[idx] = cleanse_item(key, item) return value @@ -103,7 +103,7 @@ def sanitize_item(value: Any) -> Any: return sanitize_dict(value) if isinstance(value, GeneratorType): return sanitize_item(list(value)) - if isinstance(value, list): + if isinstance(value, (list, tuple, set)): new_values = [] for item in value: new_value = sanitize_item(item) diff --git a/authentik/policies/tests/test_process.py b/authentik/policies/tests/test_process.py index 33cd56350..fa880e13b 100644 --- a/authentik/policies/tests/test_process.py +++ b/authentik/policies/tests/test_process.py @@ -3,10 +3,12 @@ from django.contrib.auth.models import AnonymousUser from django.core.cache import cache from django.test import RequestFactory, TestCase from django.urls import resolve, reverse +from django.views.debug import SafeExceptionReporterFilter from guardian.shortcuts import get_anonymous_user from authentik.core.models import Application, Group, User from authentik.events.models import Event, EventAction +from authentik.lib.generators import generate_id from authentik.policies.dummy.models import DummyPolicy from authentik.policies.expression.models import ExpressionPolicy from authentik.policies.models import Policy, PolicyBinding @@ -136,6 +138,15 @@ class TestPolicyProcess(TestCase): request = PolicyRequest(self.user) request.set_http_request(http_request) + request.context = { + "complex": { + "dict": {"foo": "bar"}, + "list": ["foo", "bar"], + "tuple": ("foo", "bar"), + "set": {"foo", "bar"}, + "password": generate_id(), + } + } response = PolicyProcess(binding, request, None).execute() self.assertEqual(response.passing, False) self.assertEqual(response.messages, ("dummy",)) @@ -151,6 +162,24 @@ class TestPolicyProcess(TestCase): self.assertEqual(event.context["result"]["passing"], False) self.assertEqual(event.context["result"]["messages"], ["dummy"]) self.assertEqual(event.client_ip, "127.0.0.1") + # Python sets don't preserve order when converted to list, + # so ensure we sort the converted set + event.context["request"]["context"]["complex"]["set"].sort() + self.assertEqual( + event.context["request"]["context"], + { + "complex": { + "set": [ + "bar", + "foo", + ], + "dict": {"foo": "bar"}, + "list": ["foo", "bar"], + "tuple": ["foo", "bar"], + "password": SafeExceptionReporterFilter.cleansed_substitute, + } + }, + ) def test_execution_logging_anonymous(self): """Test policy execution creates event with anonymous user"""