From 19a6e4bec4dfb61951079ddf50add67505c20fb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Malte=20H=C3=BCbner?= Date: Mon, 13 Jul 2026 16:20:37 +0200 Subject: [PATCH] Validate geocoding search query, return 400 instead of 500 The public /search/query proxy passed $request->query->get('query') straight into Geocoder::query(string), so a missing parameter produced a TypeError -> HTTP 500 instead of a 400. Add server-side validation: trim the input and require a length between 2 and 128 characters, returning HTTP 400 with a message otherwise. Non-scalar array input (?query[]=x) is already rejected by Symfony's InputBag as a 400. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/Controller/TypeaheadController.php | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/Controller/TypeaheadController.php b/src/Controller/TypeaheadController.php index 7b18c927..a6e112c2 100644 --- a/src/Controller/TypeaheadController.php +++ b/src/Controller/TypeaheadController.php @@ -13,6 +13,9 @@ class TypeaheadController extends AbstractController { + private const int MIN_QUERY_LENGTH = 2; + private const int MAX_QUERY_LENGTH = 128; + public function prefetchCitiesAction(RouterInterface $router): Response { $cityList = $this->managerRegistry->getRepository(City::class)->findAll(); @@ -60,8 +63,17 @@ public function prefetchStationsAction(RouterInterface $router): Response public function searchAction(Request $request, GeocoderInterface $geocoder): Response { + $queryString = trim((string) $request->query->get('query', '')); + + if (mb_strlen($queryString) < self::MIN_QUERY_LENGTH || mb_strlen($queryString) > self::MAX_QUERY_LENGTH) { + return new JsonResponse( + ['error' => sprintf('Die Suchanfrage muss zwischen %d und %d Zeichen lang sein.', self::MIN_QUERY_LENGTH, self::MAX_QUERY_LENGTH)], + Response::HTTP_BAD_REQUEST + ); + } + try { - $result = $geocoder->query($request->query->get('query')); + $result = $geocoder->query($queryString); } catch (QuotaExceeded) { return new JsonResponse(['error' => 'Die Suche ist momentan überlastet. Bitte versuche es in einigen Sekunden erneut.'], Response::HTTP_TOO_MANY_REQUESTS); }