fix(security): grant private AI endpoints by exact origin, dialled pinned

ALLOW_LOCAL_AI_PRIVATE_HOSTS=true let any user of the instance point the
Local provider or the OpenAI-compatible gateway at any private address
the server could reach, the metadata range included, and a granted host
was dialled with no connect-time pin at all.

AI_PRIVATE_ORIGINS grants a private AI endpoint with the exact-origin
grammar NOTIFICATION_PRIVATE_ORIGINS and NIGHTSCOUT_PRIVATE_ORIGINS use.
A granted call goes through the pinned operator-approved dispatcher:
redirects forbidden, and metadata, link-local and unspecified answers
dropped at dial time even for a granted name. Everything else stays on
the public pin. The Local client (buffered and streaming) and the
gateway and admin-key tags of the OpenAI client all take their policy
from one function.

The host-list form of ALLOW_LOCAL_AI_PRIVATE_HOSTS keeps working with the
same pinning; a never-grantable literal or a host:port entry is refused
with a one-time warning. Its "true" form grants nothing any more and is
reported in the boot readiness summary with the replacement.

A failed lab-report scan no longer puts the endpoint's response body into
the wide event; status and model stay. The response to the caller never
carried it.
This commit is contained in:
Marc-André Bombeck committed 2026-09-26 19:46:11 +02:00
1 parent f7b3ce6ee0
commit 1a674cf4b0
20 files changed
+508 -181

No files matched your search

+8 -4
View File
@@ -109,10 +109,14 @@ API_TOKEN_HMAC_KEY="REPLACE-WITH-OUTPUT-OF-openssl-rand-hex-32"
# Users bring their own API keys via Settings. No server-side key needed by
# default. The admin can configure a fallback key in the Admin Panel.
# Local-AI SSRF opt-in (optional). The local AI provider rejects private/
# internal hosts by default. Set to an exact host allowlist (comma-separated,
# e.g. "ollama.lan,10.0.0.5") or "true" for any private host — intended for a
# self-hosted Ollama / LM Studio endpoint. See docs/integrations/ai-providers.md.
# AI endpoints on your own network (optional). An AI base URL on a private
# address is refused unless its exact origin is listed here, comma-separated
# (e.g. "http://ollama.lan:11434,http://10.0.0.5:4000") — for a self-hosted
# Ollama, LM Studio or LiteLLM gateway. Link-local, metadata and unspecified
# addresses stay refused even when listed. See docs/integrations/ai-providers.md.
# AI_PRIVATE_ORIGINS=""
# Older form, kept for existing installs: an exact host list still works
# (e.g. "ollama.lan,10.0.0.5"). "true" no longer opens every private host.
# ALLOW_LOCAL_AI_PRIVATE_HOSTS=""
# Daily-briefing output-token ceiling (optional). Default 2500, clamped to