/** * The guarded fetch behind `import_agent_package`. * * Separated from the policy so the DECISIONS stay unit-testable without a * network, and the I/O stays small enough to audit by eye. * * Three properties this file exists to guarantee, all from §15 A1: * * 1. **Every hop is re-checked.** An allowlisted origin that redirects to a * disallowed one is the obvious bypass. `fetch()` follows redirects * silently by default, so redirect following is done MANUALLY here with * `redirect: "manual"` — automatic following would check only the first * URL and fetch the last. * * 2. **DNS is not trusted.** The resolved address is checked against the * private/metadata denylist on every hop, because an allowlisted NAME may * still answer with `169.254.169.254`. * * 3. **Response bodies never reach an error, a log line or the transcript.** * The agent reading this is the same agent an attacker may be talking to; * echoing a body back is the exfiltration channel the allowlist exists to * close. * * @module */ import { IMPORT_FETCH_LIMITS, type ImportPolicy } from "./agent-package-import-policy.js"; export interface ImportFetchResult { bytes: Buffer; /** The final URL after any permitted redirects. */ finalUrl: string; /** Each URL visited, in order — useful in an audit record. */ hops: string[]; } export declare class ImportRefusedError extends Error { readonly code = "AGENT_PACKAGE_IMPORT_REFUSED"; /** The URL that was refused, credentials already stripped. */ readonly url: string | undefined; constructor(message: string, url?: string); } /** * Resolve a hostname and refuse if ANY answer is in blocked space. * * "Any" rather than "the one we will use" on purpose: a name that resolves to * both a public and a private address is a DNS-rebinding setup, and we have no * way to pin which record the socket will actually take. */ export declare function assertHostResolvesPublicly(hostname: string, resolver?: { lookup: (h: string, opts: any) => Promise>; }): Promise; /** * Fetch a package from an allowlisted origin, or refuse. * * `fetchImpl` and `resolver` are injectable so the guard logic can be tested * against redirect chains and hostile DNS without a network. */ export declare function guardedImportFetch(rawUrl: string, policy: ImportPolicy, opts?: { fetchImpl?: typeof fetch; resolver?: { lookup: (h: string, o: any) => Promise>; }; limits?: typeof IMPORT_FETCH_LIMITS; signal?: AbortSignal; }): Promise; //# sourceMappingURL=agent-package-import-fetch.d.ts.map