diff --git a/cmd/server/routes.go b/cmd/server/routes.go index 3346e430..24301052 100644 --- a/cmd/server/routes.go +++ b/cmd/server/routes.go @@ -501,6 +501,13 @@ func (s *Server) handlePutConfigGeoFilter(w http.ResponseWriter, r *http.Request } } + // bufferKm must be finite, non-negative, and ≤ 20000 km (half Earth circumference). + if math.IsNaN(body.BufferKm) || math.IsInf(body.BufferKm, 0) || + body.BufferKm < 0 || body.BufferKm > 20000 { + writeError(w, http.StatusBadRequest, "bufferKm must be a finite number in [0, 20000]") + return + } + var gf *GeoFilterConfig if len(body.Polygon) >= 3 { gf = &GeoFilterConfig{Polygon: body.Polygon, BufferKm: body.BufferKm} diff --git a/cmd/server/routes_test.go b/cmd/server/routes_test.go index f87e3673..a45d74e1 100644 --- a/cmd/server/routes_test.go +++ b/cmd/server/routes_test.go @@ -4149,6 +4149,32 @@ func TestPutConfigGeoFilter(t *testing.T) { t.Fatalf("expected 401, got %d", w.Code) } }) + + t.Run("rejects negative bufferKm", func(t *testing.T) { + _, router, _ := setupGeoFilterServer(t, apiKey) + body := `{"polygon":[[51.0,4.0],[51.0,5.0],[50.5,4.0]],"bufferKm":-1}` + req := httptest.NewRequest("PUT", "/api/config/geo-filter", strings.NewReader(body)) + req.Header.Set("X-API-Key", apiKey) + req.Header.Set("Content-Type", "application/json") + w := httptest.NewRecorder() + router.ServeHTTP(w, req) + if w.Code != http.StatusBadRequest { + t.Fatalf("expected 400 for negative bufferKm, got %d: %s", w.Code, w.Body.String()) + } + }) + + t.Run("rejects excessive bufferKm", func(t *testing.T) { + _, router, _ := setupGeoFilterServer(t, apiKey) + body := `{"polygon":[[51.0,4.0],[51.0,5.0],[50.5,4.0]],"bufferKm":99999999}` + req := httptest.NewRequest("PUT", "/api/config/geo-filter", strings.NewReader(body)) + req.Header.Set("X-API-Key", apiKey) + req.Header.Set("Content-Type", "application/json") + w := httptest.NewRecorder() + router.ServeHTTP(w, req) + if w.Code != http.StatusBadRequest { + t.Fatalf("expected 400 for excessive bufferKm, got %d: %s", w.Code, w.Body.String()) + } + }) } func TestSaveGeoFilter(t *testing.T) {