fix(security): resolve SSRF lint errors

This commit is contained in:
Alisa Novikova
2026-03-09 14:17:55 -07:00
parent 1bd3e11985
commit 22160ff961
2 changed files with 6 additions and 12 deletions

View File

@@ -35,6 +35,7 @@ import {
isPrivateIpAsync, isPrivateIpAsync,
safeLookup, safeLookup,
isLoopbackHost, isLoopbackHost,
safeFetch,
} from '../utils/fetch.js'; } from '../utils/fetch.js';
import { debugLogger } from '../utils/debugLogger.js'; import { debugLogger } from '../utils/debugLogger.js';
@@ -58,11 +59,6 @@ interface InternalGrpcExtensions {
grpcChannelOptions: Record<string, unknown>; grpcChannelOptions: Record<string, unknown>;
} }
// Local extension of RequestInit to support Node.js/undici dispatcher
interface NodeFetchInit extends RequestInit {
dispatcher?: UndiciAgent;
}
// Remote agents can take 10+ minutes (e.g. Deep Research). // Remote agents can take 10+ minutes (e.g. Deep Research).
// Use a dedicated dispatcher so the global 5-min timeout isn't affected. // Use a dedicated dispatcher so the global 5-min timeout isn't affected.
const A2A_TIMEOUT = 1800000; // 30 minutes const A2A_TIMEOUT = 1800000; // 30 minutes
@@ -74,10 +70,8 @@ const a2aDispatcher = new UndiciAgent({
lookup: safeLookup, lookup: safeLookup,
}, },
}); });
const a2aFetch: typeof fetch = (input, init) => { const a2aFetch: typeof fetch = (input, init) =>
const nodeInit: NodeFetchInit = { ...init, dispatcher: a2aDispatcher }; safeFetch(input, { ...init, dispatcher: a2aDispatcher });
return fetch(input, nodeInit as RequestInit);
};
/** /**
* Orchestrates communication with remote A2A agents. * Orchestrates communication with remote A2A agents.

View File

@@ -240,16 +240,16 @@ function handleFetchError(error: unknown, url: string): never {
*/ */
export async function safeFetch( export async function safeFetch(
input: RequestInfo | URL, input: RequestInfo | URL,
init?: RequestInit, init?: NodeFetchInit,
): Promise<Response> { ): Promise<Response> {
const nodeInit: NodeFetchInit = { const nodeInit: NodeFetchInit = {
...init,
dispatcher: safeDispatcher, dispatcher: safeDispatcher,
...init,
}; };
try { try {
// eslint-disable-next-line no-restricted-syntax // eslint-disable-next-line no-restricted-syntax
return await fetch(input, nodeInit); return await fetch(input, nodeInit as RequestInit);
} catch (error) { } catch (error) {
const url = const url =
input instanceof Request input instanceof Request