mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-07-10 12:17:11 +00:00
fix(security): validate integration api_call URLs with the outbound SSRF guard (#5145)
execute_api_call — reachable by the LLM through the api_call agent tool — joined the integration's user-configured base_url with an LLM-controlled path and requested it with no IP validation, so a base_url (or a hostname resolving) into the metadata range (169.254.169.254) was fetched server-side with the integration's auth headers attached. Run check_outbound_url on the joined URL before connecting, matching the gallery endpoint, embeddings, CardDAV, and reminder webhook surfaces. Link-local/metadata is always rejected; INTEGRATION_API_BLOCK_PRIVATE_IPS=true also blocks RFC-1918/loopback. Private stays allowed by default because LAN integrations (Home Assistant, Miniflux, ntfy) are the primary use case. The truncation-test helpers stub the guard open because their api.example.com fixture host does not resolve and the guard fails closed on DNS errors. Fixes #5143 Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -83,6 +83,9 @@ async def _call(json_data, status=200):
|
||||
with (
|
||||
patch.object(integrations, "_find_integration", return_value=DUMMY_INTEGRATION),
|
||||
patch("httpx.AsyncClient", return_value=mock_client),
|
||||
# api.example.com doesn't resolve; the SSRF guard would fail closed.
|
||||
# These tests are about truncation, so stub the guard open.
|
||||
patch("src.url_safety.check_outbound_url", return_value=(True, "ok")),
|
||||
):
|
||||
return await integrations.execute_api_call("test_integ", "GET", "/items")
|
||||
|
||||
@@ -98,6 +101,9 @@ async def _call_with_integration(integration, path="/items"):
|
||||
with (
|
||||
patch.object(integrations, "_find_integration", return_value=integration),
|
||||
patch("httpx.AsyncClient", return_value=mock_client),
|
||||
# api.example.com doesn't resolve; the SSRF guard would fail closed.
|
||||
# These tests are about URL joining, so stub the guard open.
|
||||
patch("src.url_safety.check_outbound_url", return_value=(True, "ok")),
|
||||
):
|
||||
result = await integrations.execute_api_call("test_integ", "GET", path)
|
||||
return result, mock_client
|
||||
|
||||
Reference in New Issue
Block a user