AbsoluteJS

Egress

@absolutejs/egressv0.2.0betaAI

Deny-by-default outbound network policy and credential-safe fetch for AI agents.

#Installation

BASH
bun add @absolutejs/egress

#Capabilities

Overview

Deny-by-default outbound networking for AI agents. The package authorizes an exact HTTPS destination, resolves every address, rejects private/local/reserved networks, re-runs policy after every redirect, injects credentials only after authorization, bounds response size, and emits audit events.

DNS-rebinding-safe transport

The transport is required rather than defaulting to global fetch. A production transport must connect to one of decision.resolution.addresses while retaining the original hostname for TLS SNI and certificate verification. That closes the DNS-rebinding gap between policy resolution and the actual socket connection. createPinnedHttpsTransport() supplies that production transport. It runs inside Bun, pins the authorized address at connection time, preserves the original hostname for TLS, retries the other authorized addresses, and bounds bytes while reading the socket. It does not launch Node or a child process.

Credential isolation

Caller-supplied Authorization, Cookie, Host, and Proxy-Authorization headers are always stripped. Credentials come only from the scoped provider and are recomputed for each redirect destination.

Outcomes

What you can build

Overview

Deny-by-default outbound networking for AI agents. The package authorizes an exact HTTPS destination, resolves every address, rejects private/local/reserved networks, re-runs policy after every redirect, injects credentials only after authorization, bounds response size, and emits audit events.

DNS-rebinding-safe transport

The transport is required rather than defaulting to global fetch. A production transport must connect to one of decision.resolution.addresses while retaining the original hostname for TLS SNI and certificate verification. That closes the DNS-rebinding gap between policy resolution and the actual socket connection. createPinnedHttpsTransport() supplies that production transport. It runs inside Bun, pins the authorized address at connection time, preserves the original hostname for TLS, retries the other authorized addresses, and bounds bytes while reading the socket. It does not launch Node or a child process.

Credential isolation

Caller-supplied Authorization, Cookie, Host, and Proxy-Authorization headers are always stripped. Credentials come only from the scoped provider and are recomputed for each redirect destination.

Hardening checklist

Production guidance

DNS-rebinding-safe transportThe transport is required rather than defaulting to global fetch. A production transport must connect to one of decision.resolution.addresses while retaining the original hostname for TLS SNI and certificate verification. That closes the DNS-rebinding gap between policy resolution and the actual socket connection. createPinnedHttpsTransport() supplies that production transport. It runs inside Bun, pins the authorized address at connection time, preserves the original hostname for TLS, retries the other authorized addresses, and bounds bytes while reading the socket. It does not launch Node or a child process.

Follow in order

Troubleshooting path

1
Trace from the first failed boundary
Reproduce the smallest canonical @absolutejs/egress example, confirm the supported entry point and version in the API explorer, then inspect the first boundary that did not produce its documented result.

#Quick start

Partial snippet

Working example for Quick start.

TS
const policy = createEgressPolicy({
  allowedHosts: ["api.stripe.com", "*.githubusercontent.com"],
  resolver: resolvePublicDns,
});

const agentFetch = createEgressFetch({
  policy,
  transport: createPinnedHttpsTransport(),
  credentials: ({ url }) =>
    url.hostname === "api.stripe.com"
      ? { authorization: `Bearer ${stripeToken}` }
      : undefined,
  audit: writeSecurityEvent,
});

#Public entry points

Supported entry points declared by this project’s package manifest. Internal dist paths are not part of the package contract.

Public package entry point declared in package.json.

@absolutejs/egress@absolutejs/egress/manifest@absolutejs/egress/manifest.json

#Package commands

Scripts declared by this project’s package manifest.

bun run buildrm -rf dist && bun build src/index.ts src/manifest.ts --outdir dist --target=bun --external @sinclair/typebox && tsc -p tsconfig.build.json && absolute-manifest emit
bun run check:packagebun run format && bun run typecheck && bun run test && bun run build
bun run formatprettier --write "./**/*.{ts,json,md}"
bun run testbun test
bun run typechecktsc --noEmit

#API reference

Search the declarations exported by the current package type files. Expand a symbol to inspect its source-backed signature.

12 symbols
EgressResolutiontypePermalink
TS
type EgressResolution = {
    addresses: string[];
    hostname: string;
    resolvedAt: number;
};
Exported from @absolutejs/egress