fix(security): prevent API key leakage to non-authoritative custom endpoints

Custom endpoint provider was forwarding OPENAI_API_KEY and OLLAMA_API_KEY
to arbitrary hosts. Keys should only be sent to their authoritative domains
(openai.com, ollama.com) or when explicitly configured via pool/env.

- Gate OPENAI_API_KEY to openai.com hosts only
- Gate OLLAMA_API_KEY to ollama.com hosts only
- Return 'no-key-required' for unrecognized custom endpoints
- Update tests to reflect secure-by-default behavior

Closes #28660
This commit is contained in:
Erhnysr 2026-05-19 21:34:59 +03:00 committed by Teknium
parent 5672772dab
commit 59088228f6
2 changed files with 89 additions and 10 deletions

View file

@ -721,13 +721,19 @@ def _resolve_openrouter_runtime(
# "ollama.com" (e.g. http://127.0.0.1/ollama.com/v1) or whose
# hostname is a look-alike (ollama.com.attacker.test) must not
# receive the Ollama credential. See GHSA-76xc-57q6-vm5m.
_is_ollama_url = base_url_host_matches(base_url, "ollama.com")
_is_ollama_url = base_url_host_matches(base_url, "ollama.com")
_is_openai_url = base_url_host_matches(base_url, "openai.com")
_is_openai_azure = base_url_host_matches(base_url, "openai.azure.com")
# Gate each provider key on its own host — sending OPENAI_API_KEY or
# OPENROUTER_API_KEY to an unrelated custom endpoint (DeepSeek, Groq,
# Mistral, …) leaks credentials and causes 401s (issue #28660).
# Mirrors the OLLAMA_API_KEY host-gate added in GHSA-76xc-57q6-vm5m.
api_key_candidates = [
explicit_api_key,
(cfg_api_key if use_config_base_url else ""),
(os.getenv("OLLAMA_API_KEY") if _is_ollama_url else ""),
os.getenv("OPENAI_API_KEY"),
os.getenv("OPENROUTER_API_KEY"),
(os.getenv("OLLAMA_API_KEY") if _is_ollama_url else ""),
(os.getenv("OPENAI_API_KEY") if (_is_openai_url or _is_openai_azure) else ""),
(os.getenv("OPENROUTER_API_KEY") if _is_openrouter_url else ""),
]
api_key = next(
(str(candidate or "").strip() for candidate in api_key_candidates if has_usable_secret(candidate)),