From 3d4d24536420e74650da62da0e55f0dfdc52566f Mon Sep 17 00:00:00 2001 From: vishal Date: Wed, 14 Oct 2026 23:32:46 +0530 Subject: [PATCH] fix(web): enforce MAX_ITEMS_PER_PAGE cap on find_node_by_name --- application/tests/web_main_test.py | 46 ++++++++++++++++++++++++++++++ application/web/web_main.py | 3 +- 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/application/tests/web_main_test.py b/application/tests/web_main_test.py index 13b30f921..0c2995b44 100644 --- a/application/tests/web_main_test.py +++ b/application/tests/web_main_test.py @@ -434,6 +434,52 @@ def test_find_node_by_name(self) -> None: ] self.assertCountEqual(expected, actual) + @patch.object(db, "Node_collection") + def test_find_node_by_name_caps_items_per_page(self, db_mock) -> None: + """find_node_by_name clamps items_per_page to MAX_ITEMS_PER_PAGE.""" + db_mock.return_value.get_nodes_with_pagination.return_value = (1, [], []) + + with self.app.test_client() as client: + client.get( + "/rest/v1/standard/OWASP%20Top%2010?items_per_page=9999", + headers={"Content-Type": "application/json"}, + ) + + _, kwargs = db_mock.return_value.get_nodes_with_pagination.call_args + self.assertEqual(kwargs["items_per_page"], web_main.MAX_ITEMS_PER_PAGE) + + def test_find_node_by_name_items_per_page_cap_integration(self) -> None: + """find_node_by_name caps items_per_page at MAX_ITEMS_PER_PAGE against a real database.""" + collection = db.Node_collection() + standard_name = "CapTestStandard" + for i in range(110): + collection.add_node( + defs.Standard( + name=standard_name, + section=f"section-{i}", + ) + ) + collection.session.commit() + + with self.app.test_client() as client: + # Requesting more than MAX should be silently capped. + response = client.get( + f"/rest/v1/standard/{standard_name}?items_per_page=9999&page=1", + headers={"Content-Type": "application/json"}, + ) + self.assertEqual(200, response.status_code) + body = json.loads(response.data) + self.assertLessEqual(len(body["standards"]), web_main.MAX_ITEMS_PER_PAGE) + + # Default (no items_per_page) should apply ITEMS_PER_PAGE. + response = client.get( + f"/rest/v1/standard/{standard_name}?page=1", + headers={"Content-Type": "application/json"}, + ) + self.assertEqual(200, response.status_code) + body = json.loads(response.data) + self.assertEqual(len(body["standards"]), web_main.ITEMS_PER_PAGE) + def test_find_document_by_tag(self) -> None: collection = db.Node_collection() cres = { diff --git a/application/web/web_main.py b/application/web/web_main.py index 094f818e8..7c23ab10a 100644 --- a/application/web/web_main.py +++ b/application/web/web_main.py @@ -258,7 +258,8 @@ def find_node_by_name( page = 1 if request.args.get("page") is not None and int(request.args.get("page")) > 0: page = request.args.get("page") - items_per_page = request.args.get("items_per_page") or ITEMS_PER_PAGE + items_per_page = int(request.args.get("items_per_page") or ITEMS_PER_PAGE) + items_per_page = min(items_per_page, MAX_ITEMS_PER_PAGE) include_only = request.args.getlist("include_only") total_pages, nodes = None, None