From 3e2a60ad143375a92d521a534a4ec4ea66003e7e Mon Sep 17 00:00:00 2001 From: Michael Genson Date: Thu, 14 May 2026 19:22:31 +0000 Subject: [PATCH] protect order_by too --- mealie/repos/repository_generic.py | 3 ++- .../test_query_filter_builder.py | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/mealie/repos/repository_generic.py b/mealie/repos/repository_generic.py index 414574105..9c76a1e69 100644 --- a/mealie/repos/repository_generic.py +++ b/mealie/repos/repository_generic.py @@ -26,6 +26,7 @@ from mealie.schema.response.pagination import ( ) from mealie.schema.response.query_search import SearchFilter from mealie.services.query_filter.builder import QueryFilterBuilder +from mealie.services.query_filter.context import allow_filter_restricted from ._utils import NOT_SET, NotSet @@ -460,7 +461,7 @@ class RepositoryGeneric[Schema: MealieModel, Model: SqlAlchemyBase]: order_dir = request_query.order_direction _, order_attr, query = QueryFilterBuilder.get_model_and_model_attr_from_attr_string( - order_by, self.model, query=query + order_by, self.model, query=query, allow_restricted=allow_filter_restricted.get() ) query = self.add_order_attr_to_query( diff --git a/tests/unit_tests/repository_tests/test_query_filter_builder.py b/tests/unit_tests/repository_tests/test_query_filter_builder.py index b83b055d8..1f481c179 100644 --- a/tests/unit_tests/repository_tests/test_query_filter_builder.py +++ b/tests/unit_tests/repository_tests/test_query_filter_builder.py @@ -153,3 +153,20 @@ def test_filter_query_respects_context_var_true(): builder = QueryFilterBuilder("user.email = 'test@example.com'") # Should not raise builder.filter_query(query, RecipeModel) + + +# --------------------------------------------------------------------------- +# orderBy restricted traversal tests +# --------------------------------------------------------------------------- + + +def test_order_by_restricted_traversal_blocked(): + """get_model_and_model_attr_from_attr_string with allow_restricted=False blocks orderBy into User.""" + with pytest.raises(ValueError, match="restricted model"): + QueryFilterBuilder.get_model_and_model_attr_from_attr_string("user.email", RecipeModel, allow_restricted=False) + + +def test_order_by_private_field_blocked(): + """Ordering by a PrivateColumn field should always raise, regardless of allow_restricted.""" + with pytest.raises(ValueError, match="private field"): + QueryFilterBuilder.get_model_and_model_attr_from_attr_string("password", User, allow_restricted=True)