How OpenWork Manages Outbound Access Control for Enterprise Deployments

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 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/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.

// 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/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.

// 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:

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.
// 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/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 to define all permissible outbound network destinations for enterprise deployments.
  • The outboundManifestFromUnknown function in egress.ts loads and caches the manifest at startup, while safeExternalMcpOutbound in 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. This guard validates the destination host against a pre-approved manifest (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 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 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 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 test suite provides a reference implementation for validating enforcement behavior.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →