Fix private AI custom endpoints (#1299)

This commit is contained in:
ZacharyZcR
2026-08-23 22:38:03 +08:00
committed by GitHub
parent fbf267fe5f
commit b5d13c3664
5 changed files with 50 additions and 10 deletions
+10 -5
View File
@@ -51,8 +51,7 @@ function normalizeHost(hostname: string): string {
/**
* True when the URL names a destination the SSRF guard would refuse. A bare
* hostname that is not an IP literal (e.g. "ollama.internal") is treated as
* private only if it is "localhost" -- anything else resolves through DNS and
* is caught at connect time by the guard instead.
* private only if it is "localhost" -- anything else needs DNS resolution.
*/
export function isPrivateDestination(rawUrl: string): boolean {
let url: URL;
@@ -98,12 +97,18 @@ export function evaluateEgress(
const host = normalizeHost(url.hostname);
const isPrivate = isPrivateDestination(rawUrl);
const normalized = allowlist.map((entry) => entry.trim().toLowerCase());
// An explicitly allowlisted hostname may resolve to a private address. It
// must use the private fetch path; sending it through safeOutboundFetch
// would reject it after DNS resolution and make hostname allowlist entries
// ineffective. Only administrators can write this list.
if (normalized.includes(host)) {
return { allowed: true, isPrivate: true };
}
if (!isPrivate) return { allowed: true, isPrivate: false };
const normalized = allowlist.map((entry) => entry.trim().toLowerCase());
if (normalized.includes(host)) return { allowed: true, isPrivate: true };
return {
allowed: false,
isPrivate: true,
+10
View File
@@ -61,6 +61,16 @@ describe("evaluateEgress", () => {
expect(decision.isPrivate).toBe(true);
});
it.each(["llm.internal", "host.docker.internal"])(
"routes allowlisted private DNS name %s through the private path",
(host) => {
expect(evaluateEgress(`http://${host}:8000/v1`, [host])).toEqual({
allowed: true,
isPrivate: true,
});
},
);
it("matches the allowlist case-insensitively", () => {
expect(
evaluateEgress("http://LOCALHOST:11434", ["localhost"]).allowed,