diff --git a/src/lib/ai/anthropic-client.ts b/src/lib/ai/anthropic-client.ts index 903e3c88a..4228fd322 100644 --- a/src/lib/ai/anthropic-client.ts +++ b/src/lib/ai/anthropic-client.ts @@ -54,7 +54,9 @@ export class AnthropicClient implements AIProvider { }), }, // 60 s ceiling — see openai-client.ts for the rationale. - { timeoutMs: 60_000 }, + // v1.11.2 — base URL is user/admin-overridable; pin the connect-time DNS + // check so a private/metadata address is rejected (SSRF/rebinding). + { timeoutMs: 60_000, requirePublicHost: true }, ); if (!res.ok) { diff --git a/src/lib/ai/openai-client.ts b/src/lib/ai/openai-client.ts index 06a3b3a00..a898acaed 100644 --- a/src/lib/ai/openai-client.ts +++ b/src/lib/ai/openai-client.ts @@ -52,7 +52,10 @@ export class OpenAIClient implements AIProvider { }, // 60 s ceiling so a tar-pit upstream cannot pin a worker // indefinitely. Real completions land well inside this budget. - { timeoutMs: 60_000 }, + // v1.11.2 — the base URL is user/admin-overridable (BYO gateway), so pin + // the connect-time DNS check: a base URL resolving to a private/metadata + // address is rejected, closing the SSRF/rebinding surface. + { timeoutMs: 60_000, requirePublicHost: true }, ); if (!res.ok) { diff --git a/src/lib/geo.ts b/src/lib/geo.ts index e9b5b4358..c3bd9e623 100644 --- a/src/lib/geo.ts +++ b/src/lib/geo.ts @@ -300,7 +300,10 @@ async function lookupIpLocationOnline(ip: string): Promise { Accept: "application/json", }, }, - { timeoutMs: 3_000 }, + // v1.11.2 — the lookup URL comes from the operator IP_GEO_LOOKUP_URL env; + // pin the connect-time DNS check so it can't be pointed at a private / + // metadata address (SSRF/rebinding). + { timeoutMs: 3_000, requirePublicHost: true }, ); if (!res.ok) return null;