# How OpenWork Manages Outbound Access Control for Enterprise Deployments

> Learn how OpenWork secures enterprise deployments with outbound access control. It validates HTTP requests against allowed-hosts, preventing unauthorized network traffic.

- Repository: [Different AI/openwork](https://github.com/different-ai/openwork)
- Tags: how-to-guide
- Published: 2026-08-06

---

**OpenWork enforces strict outbound access control for enterprise deployments through a declarative manifest system that validates every HTTP request against an allowed-hosts list before any network traffic is emitted.**

OpenWork (different-ai/openwork) implements a defense-in-depth strategy for enterprise network security by controlling outbound traffic at the application layer. The system uses a centralized JSON manifest to define permissible external hosts, ensuring that self-hosted and cloud deployments cannot accidentally leak data or fall victim to Server-Side Request Forgery (SSRF) attacks.

## Declarative Outbound Manifest Configuration

At the heart of OpenWork's enterprise security model lies the **[`docs/enterprise/outbound-access.json`](https://github.com/different-ai/openwork/blob/main/docs/enterprise/outbound-access.json)** file. This declarative manifest enumerates every external host the application may contact, the specific component that initiates the call, and the business-level requirement classification (e.g., `required-for-cloud`, `required-in-practice`, `opt-in`, or `optional`).

Each entry documents the justification for network access, enabling security teams to audit allowances without reading source code. The manifest serves as the single source of truth for both documentation and runtime enforcement.

## Runtime Enforcement Architecture

When the OpenWork runtime initiates an HTTP request, the call is intercepted by a validation layer that consults the manifest before opening any network socket.

### Manifest Loading with outboundManifestFromUnknown

The **`outboundManifestFromUnknown`** helper function, located in [[`evals/packages/labs/src/egress.ts`](https://github.com/different-ai/openwork/blob/main/evals/packages/labs/src/egress.ts)](https://github.com/different-ai/openwork/blob/dev/evals/packages/labs/src/egress.ts), parses the JSON manifest at startup and builds an in-memory lookup table of allowed hosts. This table is cached for the application lifecycle to minimize runtime overhead.

```typescript
// evals/packages/labs/src/egress.ts
import { outboundManifestFromUnknown, startEgressLab } from "@openwork/labs";
import { readFile } from "fs/promises";
import { join } from "path";

const manifestPath = join(__dirname, "..", "docs", "enterprise", "outbound-access.json");

// Load the manifest once at startup
const manifest = outboundManifestFromUnknown(JSON.parse(await readFile(manifestPath, "utf8")));

```

### URL Guard Implementation

All outbound fetches route through **`safeExternalMcpOutbound`**, implemented in [[`ee/apps/den-api/src/capability-sources/url-guard.ts`](https://github.com/different-ai/openwork/blob/main/ee/apps/den-api/src/capability-sources/url-guard.ts)](https://github.com/different-ai/openwork/blob/dev/ee/apps/den-api/src/capability-sources/url-guard.ts). This wrapper checks the request URL against the manifest lookup table. If the host is absent or explicitly blocked, the function aborts the request before any packets leave the network interface and returns a structured error to the caller.

```typescript
// ee/apps/den-api/src/capability-sources/url-guard.ts
async function safeFetch(url: string, init?: RequestInit) {
  // `startEgressLab` creates a request wrapper that validates the host
  const egress = startEgressLab({ manifest });
  return egress.fetch(url, init); // throws if the host is not allowed
}

// Usage – this will succeed because api.openai.com is listed as required-for-cloud
await safeFetch("https://api.openai.com/v1/chat/completions");

// Usage – this will throw because an unknown host is not in the manifest
await safeFetch("https://unknown.badhost.example"); // ❌ Blocked by outbound policy

```

## Policy Enforcement Points

The URL guard is injected at multiple architectural layers to ensure comprehensive coverage:

- **MCP Client Layer**: The contract definition in [[`packages/enterprise-mcp-client/src/contracts.ts`](https://github.com/different-ai/openwork/blob/main/packages/enterprise-mcp-client/src/contracts.ts)](https://github.com/different-ai/openwork/blob/dev/packages/enterprise-mcp-client/src/contracts.ts) mandates that the composition root "owns SSRF, DNS rebinding" protection, making the guard a mandatory prerequisite for every MCP-initiated request.

- **Den-API Server Layer**: Capability sources such as [`external-mcp-tool-inspection.ts`](https://github.com/different-ai/openwork/blob/main/external-mcp-tool-inspection.ts) and [`external-mcp-diagnostics.ts`](https://github.com/different-ai/openwork/blob/main/external-mcp-diagnostics.ts) invoke the guard before forwarding requests to remote MCP servers. Errors generated here surface in the UI components like the outbound tools diagnostics panel in [`ee/apps/den-web/app/(den)/dashboard/_components/mcp-tool-error-attribution.ts`](https://github.com/different-ai/openwork/blob/dev/ee/apps/den-web/app/(den)/dashboard/_components/mcp-tool-error-attribution.ts).

## Dynamic Host Overrides for Self-Hosted Mirrors

Enterprises operating behind corporate proxies or using self-hosted mirrors can override specific endpoints via environment variables without modifying the codebase. The guard respects these overrides during validation.

Common override variables include:

- **`OPENWORK_GITHUB_API_BASE`** – Redirects GitHub API calls from `api.github.com` to an internal GitHub Enterprise instance.
- **`OPENCODE_MODELS_URL`** – Points the OpenCode model catalog to an internal registry.
- **`VITE_OPENWORK_POSTHOG_HOST`** – Changes the optional analytics endpoint to an internal PostHog instance.

```typescript
// Override example for corporate GitHub Enterprise
process.env.OPENWORK_GITHUB_API_BASE = "https://github.mycorp.com/api";

// The guard treats github.mycorp.com as the allowed target
await safeFetch(`${process.env.OPENWORK_GITHUB_API_BASE}/repos/...`);

```

The manifest entry's `override` field documents the associated environment variable, ensuring configuration remains discoverable.

## Enterprise Policy Categories

The manifest categorizes hosts by criticality to support tiered security postures:

- **`required-for-cloud`**: Essential for hosted OpenWork Cloud deployments (e.g., `api.openworklabs.com`, `app.openworklabs.com`). Blocking these disables installer checks, sign-in flows, and marketplace access.
- **`required-in-practice`**: Essential for self-hosted Den installations (e.g., `github.com`, `ghcr.io`). Blocking these stops container image pulls or installer downloads, causing the deployment to fail early with a clear error message referencing the manifest file.
- **`optional`** and **`opt-in`**: Only contacted when specific features are enabled (e.g., `cdn.simpleicons.org` for icons, `mcp.slack.com` for Slack integration). The guard validates these even when enabled to prevent accidental bypasses.

## Diagnostics and Audit Logging

When the URL guard blocks a request, OpenWork generates a diagnostic payload that includes the manifest path and a human-readable explanation. This enables security teams to identify exactly which policy triggered the denial.

```

BLOCKED HOST / PROXY DENY: api.github.com is blocked by the selective-deny profile; docs/enterprise/outbound-access.json names the required host and its blocked effect.

```

The error attribution flows through to the web dashboard, allowing administrators to correlate blocked requests with specific capability sources and adjust the allow-list accordingly. The enforcement logic is validated by the test suite in [[`evals/specs/egress-selective-deny.test.ts`](https://github.com/different-ai/openwork/blob/main/evals/specs/egress-selective-deny.test.ts)](https://github.com/different-ai/openwork/blob/dev/evals/specs/egress-selective-deny.test.ts), which confirms that the manifest correctly blocks unauthorized egress attempts.

## Summary

- **OpenWork** uses a declarative manifest at [`docs/enterprise/outbound-access.json`](https://github.com/different-ai/openwork/blob/main/docs/enterprise/outbound-access.json) to define all permissible outbound network destinations for enterprise deployments.
- The **`outboundManifestFromUnknown`** function in [`egress.ts`](https://github.com/different-ai/openwork/blob/main/egress.ts) loads and caches the manifest at startup, while **`safeExternalMcpOutbound`** in [`url-guard.ts`](https://github.com/different-ai/openwork/blob/main/url-guard.ts) validates every HTTP request against this allow-list.
- Environment variables like `OPENWORK_GITHUB_API_BASE` enable dynamic redirection to self-hosted mirrors without code changes.
- Hosts are categorized by criticality (`required-for-cloud`, `required-in-practice`, `optional`), allowing security teams to implement tiered access controls.
- Blocked requests generate detailed error messages referencing the manifest file, simplifying audit and compliance workflows.

## Frequently Asked Questions

### How does OpenWork prevent SSRF attacks in enterprise environments?

OpenWork prevents SSRF attacks by routing all outbound HTTP requests through a centralized URL guard implemented in [`ee/apps/den-api/src/capability-sources/url-guard.ts`](https://github.com/different-ai/openwork/blob/main/ee/apps/den-api/src/capability-sources/url-guard.ts). This guard validates the destination host against a pre-approved manifest ([`docs/enterprise/outbound-access.json`](https://github.com/different-ai/openwork/blob/main/docs/enterprise/outbound-access.json)) before any network connection is established, ensuring that requests to internal IP ranges or unauthorized external hosts are aborted immediately.

### Can we customize the outbound access list for self-hosted OpenWork deployments?

Yes. Enterprises can modify the [`docs/enterprise/outbound-access.json`](https://github.com/different-ai/openwork/blob/main/docs/enterprise/outbound-access.json) manifest to reflect their specific network requirements, or they can use environment variables to override specific endpoints. For example, setting `OPENWORK_GITHUB_API_BASE` to an internal GitHub Enterprise URL redirects all GitHub API traffic without requiring changes to the source code or manifest file.

### What happens if a required host is blocked by our corporate firewall?

If a `required-for-cloud` or `required-in-practice` host is blocked, OpenWork fails fast during initialization or the specific operation (such as container pulls or authentication flows) with a clear error message. The error explicitly references [`docs/enterprise/outbound-access.json`](https://github.com/different-ai/openwork/blob/main/docs/enterprise/outbound-access.json) and identifies which blocked host caused the failure, allowing network administrators to adjust firewall rules or proxy configurations precisely.

### Is there a way to audit which outbound requests are being blocked?

Yes. OpenWork surfaces blocked request diagnostics through multiple channels. The [`mcp-tool-error-attribution.ts`](https://github.com/different-ai/openwork/blob/main/mcp-tool-error-attribution.ts) component in the web dashboard displays blocked outbound tool calls, while the runtime logs include structured error messages indicating the blocked host and the specific manifest entry that denied the request. Additionally, the [`egress-selective-deny.test.ts`](https://github.com/different-ai/openwork/blob/main/egress-selective-deny.test.ts) test suite provides a reference implementation for validating enforcement behavior.