0.136.5
Fixed
- Local-spec на non-loopback приватном IP больше не блокируется ( follow-up): после v0.136.4 startup-блокировки исчезли, но проверка провайдера Ollama из UI всё равно падала с
request failed: Get "http://192.168.2.57:11434/api/tags": blocked internal/private IP: 192.168.2.57. Причина — два уровня SSRF-проверки рассинхронизировались для local-spec на non-loopback: валидация (pre-call) проходила (видела global whitelist черезSetSSRFGuard), а dial (runtime) использовалloopbackSSRFGuardс whitelist["127.0.0.0/8", "::1/128"]— без global подсетей. Поэтому local-spec dial по любому non-loopback приватному IP резался независимо от настроек. ЗаменёнloopbackSSRFGuard(singleton, loopback-only) наlocalSpecGuard(atomic.Pointer, combined = loopbackCIDRs + global.AllowedCIDRs), который rebuild’ится вSetSSRFGuardи вinit(). Теперь Ollama на192.168.2.57:11434проходит и валидацию, и dial.
Changed
security.SSRFGuard.AllowedCIDRs(): новый публичный метод для чтения whitelist guard’а (defensive copy, nil для no-whitelist). Нужен, чтобыproviders.rebuildLocalSpecGuardмог построить combined guard (loopback + global).providers.rebuildLocalSpecGuard(global): строитlocalSpecGuard = NewSSRFGuard(loopbackCIDRs + global.AllowedCIDRs())и кешируетlocalSpecClient(atomic.Pointer). Вызывается изinit()иSetSSRFGuard. Security-свойства: loopback (127.0.0.0/8,::1/128) всегда reachable (процесс-local модели — не SSRF-цель); non-loopback private IP reachable iff global whitelist авторизует подсеть; cloud-metadata (169.254.169.254), multicast, reserved, TEST-NET ВСЕГДА блокируются черезsecurity.blockedNetworks(blacklist precedence > whitelist).SetSSRFGuardтеперь rebuild’ит иlocalSpecGuard/localSpecClient, не толькоglobalCloudClient. Без этого UI-сменаssrf_whitelist+ restart не применялась бы к local-spec dial-пути.slog.Warnonce на fallback hit: еслиlocalSpecClientилиglobalCloudClientнеожиданно nil при lookup (regression), WARN пишется ровно один раз черезsync.Once, чтобы оператор видел деградацию в логах вместо silent per-call аллокации.- Уточнён docstring
localSpecClient: убрано преувеличенное “defence in depth” заявление — rebuild вSetSSRFGuardявляется load-bearing update’ом, не опциональным. Transport через getter видит новый guard только если клиент построен ПОСЛЕ rebuild’а; cached-клиент требует явного swap.