0.134.93
Security
- SSRF-валидация api_base для cloud-провайдеров:
ResolveAndValidateAPIBaseв новомinternal/providers/ssrf.goблокирует RFC 1918 / loopback / link-local / cloud-metadata (169.254.169.254) для cloud-провайдеров перед любым outbound-запросом. Локальные провайдеры (ollama, lmstudio, vllm) exempt только если api_base действительно loopback (IP-литерал 127.0.0.0/8/::1 илиlocalhost) — закрыт bypass через регистрациюProvider:"ollama"с api_base на метадату AWS. На rejection логируется host (без userinfo) серверсайд, клиенту возвращается generic-сообщение (не раскрывает blocklist-топологию). - DNS-rebinding / TOCTOU для model-list:
listModelsOpenAICompatиlistModelsOllamaпереведены с голого&http.Client{}наsafeHTTPClientForSpec(transport с dial-time IP re-check изsecurity.SSRFGuard.SafeHTTPClient). Local-spec использует loopback-whitelisted guard, cloud-spec — активный. pre-callValidateURLостаётся как defence-in-depth. - Anti-exfiltration для api_base override: в
Test(/providers/{id}/test) при переопределении api_base из формы сохранённый расшифрованный api_key НЕ фолбэчится — иначе API-клиент мог бы перенаправить credential на произвольный хост.
Fixed
- Валидация api_key в TestConfig: пустой api_key для cloud-провайдеров теперь 400 (раньше молча тестировался → misleading 401 или ложный success). Локальные провайдеры (ollama/lmstudio/vllm) остаются exempt.
- 413 вместо 400 на oversized body:
MaxBytesReader-ошибки в Test/TestConfig теперь возвращают413 Request Entity Too Large(черезerrors.As(*http.MaxBytesError)), а не вводящий в заблуждение400 invalid json. - writeJSONError вместо http.Error: invalid-id / not-found пути в
Testпереведены наwriteJSONErrorдля консистентной JSON-формы ответа. hasOverrideна per-field checks: дискриминатор «тело содержит override» переписан с хрупкогоbody != providerTestBody{}на явную проверкуbody.Provider != "" || body.APIKey != "" || body.APIBase != "", устойчивую к будущим полям.
Changed
maxProviderTestBodyBytes(1 « 16) как именованная константа вместо дублирующегося магического числа в Test/TestConfig.IsLocalSpec— единый source of truth для классификации local/cloud;ListModelsForSpecиResolveAndValidateAPIBaseделегируют к нему.SetSSRFGuardна atomic.Pointer: потокобезопасная установка/чтение guard’а (хотя контракт остаётся «вызов ровно один раз из main.go»).- Stale
resolveAPIBaseудалён;runDiagnosticsтеперь используетResolveAndValidateAPIBase, чтобы диагностики сообщали URL, который фактически валидировался. - Комментарий в
+page.svelteпереведён на английский и обновлён: fallback api_key отключён, если форма переопределяет api_base.
Added
- Тесты:
internal/providers/ssrf_test.go(16 тестов — SSRF для cloud/local/nil-spec, loopback-enforcement, DNS-bypass, error disclosure, atomic.Pointer contract),TestTest_APIBaseOverrideDoesNotExfiltrateSavedKey,TestTestConfig_MissingAPIKey(+ local-exempt),TestTestConfig_LocalProviderWithoutAPIKey,TestTest_InvalidID_UsesJSONError,TestTest_BodyTooLarge,TestTestConfig_BodyTooLarge.