Files
OmniRoute/open-sse/utils/anthropicHost.ts
Diego Rodrigues de Sa e Souza b3207ab010 fix(security): exact-host Anthropic baseUrl check (CodeQL js/incomplete-url-substring-sanitization #674) (#5129)
The anthropic-compatible Bearer-fallback gate decided whether a configured baseUrl
targeted the official api.anthropic.com host via a substring `.includes("api.anthropic.com")`.
A look-alike upstream such as `https://api.anthropic.com.evil.test` or
`https://evil.test/?x=api.anthropic.com` matched the substring and was wrongly treated as
official, suppressing the Bearer fallback meant for third-party gateways
(CodeQL #674, js/incomplete-url-substring-sanitization, high).

Replace the substring test with an exported `isOfficialAnthropicBaseUrl()` helper that
parses the URL and compares the hostname for exact equality. Empty baseUrl stays official;
scheme-less hosts are parsed with an assumed https://; an unparseable baseUrl falls back to
third-party (Bearer emitted) as the safer default. Behavior for legitimate official/third-party
baseUrls is unchanged.

Adds tests/unit/anthropic-official-baseurl-host.test.ts covering official, look-alike,
scheme-less, and unparseable inputs plus a static guard that the substring pattern is gone.
2026-06-26 23:14:27 -03:00

26 lines
1002 B
TypeScript

/**
* Whether a configured Anthropic `baseUrl` targets the official `api.anthropic.com` host.
*
* Uses exact hostname equality (parsed via `new URL`) instead of a substring `.includes`,
* so a look-alike upstream such as `https://api.anthropic.com.evil.test` or
* `https://evil.test/?x=api.anthropic.com` is correctly treated as third-party
* (CodeQL `js/incomplete-url-substring-sanitization`). An empty baseUrl means the default
* official endpoint; a scheme-less host (e.g. `api.anthropic.com/v1`) is parsed with an
* assumed `https://`; an unparseable baseUrl is treated as third-party (safer default —
* the Bearer fallback is then emitted).
*/
export function isOfficialAnthropicBaseUrl(baseUrl: string): boolean {
if (!baseUrl) return true;
let host: string | null = null;
try {
host = new URL(baseUrl).hostname;
} catch {
try {
host = new URL(`https://${baseUrl}`).hostname;
} catch {
return false;
}
}
return host === "api.anthropic.com";
}