--- tags: [audit, bug, security, frontend, backend, code-review] date: 2025-06-29 --- # Code Audit: 35 найденных проблем (2025-06-29) ## Критические (3) ### 1. Отсутствует go-playground/validator в go.mod - `backend/go.mod` и `backend/internal/validator/validator.go:11` - Пакет импортируется, но отсутствует в `go.mod`. - **Фикс:** `go mod tidy` или ручное добавление. ### 2. Data race на WSHub.clients - `backend/internal/handlers/websocket.go:83-109` - `broadcastVisitors()` итерация по `h.clients` без мьютекса из двух горутин. - **Фикс:** `sync.RWMutex` при чтении/записи clients. ### 3. Утечка маркеров Leaflet - `frontend/src/lib/map.ts:105-122` - `addMarker` не удаляет старый маркер с тем же ID — дубликаты в DOM. - **Фикс:** `removeMarker(id)` перед `addMarker`. ## Высокие (8) ### 4. Утечка внутреннего URL MinIO - `backend/internal/handlers/upload.go:159-164` - При ошибке `url.Parse` клиент получает `http://minio:9000/...`. ### 5. Игнорирование ошибки GetByEmail - `backend/internal/services/auth.go:85` - `backend/internal/handlers/users.go:113` - При недоступности БД дубликаты email не проверяются. ### 6-8. Stale closures в MapView - `frontend/src/components/MapView.tsx:57-69` — геолокация - `frontend/src/components/MapView.tsx:100-117` — маркеры мест - `frontend/src/components/MapView.tsx:121-133` — маркеры посетителей - Пропущен `user` в deps, stale `user` в замыкании. ### 9. WebSocket reconnect после unmount - `frontend/src/hooks/useWebSocket.ts:74-104` - `onclose` может сработать после cleanup и запустить reconnect. ### 10. Presigned upload без проверки ответа - `frontend/src/app/services/add/page.tsx:39-48` - `fetch()` на presigned URL без `res.ok`. ### 11. Логи без контекста запроса - `backend/internal/handlers/errors.go:27` - Глобальный `slog` без request_id/user_id. ## Средние (10) ### 12. Игнорирование ошибки тегов сервиса - `backend/internal/handlers/services.go:79-82` ### 13. Теги сервиса не обновляются - `backend/internal/handlers/services.go:96-103,167-193` ### 14. Неиспользуемый атомарный rotate token - `backend/internal/repository/refresh_tokens.go:66-125` ### 15. Нет LIMIT в запросах броней - `backend/internal/repository/bookings.go:83-107` ### 16. Опчатка `detail` → `details` - `frontend/src/lib/api.ts:86` ### 17. `deleted` не в PlaceStatus - `frontend/src/app/admin/page.tsx:7` ### 18. Falsy-zero для hourlyRate - `frontend/src/components/PlaceForm.tsx:98-99` ### 19. `type` в PATCH - `frontend/src/components/PlaceForm.tsx:93` ### 20. Глотание ошибки API - `frontend/src/app/places/my/page.tsx:330-336` ### 21. Нет валидации NaN координат - `frontend/src/components/PlaceForm.tsx:88-89` ## Низкие (14) ### 22. useSSL захардкожен - `backend/cmd/api/main.go:64` ### 23. Неиспользуемая ErrPlaceNotFound - `backend/internal/services/places.go:47` ### 24. Неиспользуемые валидаторы - `backend/internal/validator/validator.go:34-35` ### 25. Игнорирование ошибок парсинга query - `backend/internal/handlers/places.go:62-95` ### 26. cleanup горутина не останавливается - `backend/internal/middleware/ratelimit.go:29` ### 27. Soft delete сервиса без смены статуса - `backend/internal/repository/services.go:103` ### 28. Лишний ?. на getBounds - `frontend/src/components/MapView.tsx:76` ### 29. JSDoc: Яндекс вместо Leaflet - `frontend/src/components/MapView.tsx:13` ### 30. Избыточный ref - `frontend/src/components/MapView.tsx:41-42` ### 31. fetchPlaces не в deps - `frontend/src/app/places/my/page.tsx:338` ### 32. Двойной revokeObjectURL - `frontend/src/components/PlaceForm.tsx:55-61` ### 33. SetupHandler без интерфейса - `backend/internal/handlers/setup.go:13-17` ### 34. PlaceHandler хранит authSvc для парсинга - `backend/internal/handlers/places.go:19-26` ### 35. pointer.Str("") → nil - `backend/internal/pointer/pointer.go:3-7` ## Связанные заметки - [[MOC-security-patterns]] - [[MOC-backend-patterns]] - [[atomic-refresh-token-race-condition]] - [[atomic-error-swallowing-frontend]]