Operations

Security

Security

Proxyline is a Node-process runtime, not an operating-system sandbox. Understanding what it does — and what it cannot do — is essential before relying on it as a policy.

#What Proxyline enforces

In managed mode, Proxyline forces traffic through the configured proxy on the surfaces it covers:

  • http.request / http.get / http.globalAgent
  • https.request / https.get / https.globalAgent
  • The undici global dispatcher (i.e. fetch)
  • WebSocket clients that accept a Node agent, via proxy.createWebSocketAgent() or by reusing the patched http.request during the upgrade
  • Explicit HTTP CONNECT via openProxyConnectTunnel

Caller-supplied http.Agent / https.Agent instances are replaced per request, and createConnection overrides are stripped. TLS-relevant agent options are lifted onto the request so destination TLS still validates correctly.

In ambient mode the same surfaces are covered when at least one of HTTP_PROXY, HTTPS_PROXY, or ALL_PROXY is set, and NO_PROXY is honored.

#What Proxyline cannot enforce

Anything that does not flow through the patched APIs:

  • Direct net.connect or tls.connect calls. Code that opens raw sockets is not seen by Proxyline.
  • Native modules with private transport stacks (e.g. some database drivers, gRPC C bindings).
  • Libraries that own their own Dispatcher and pass it explicitly to undici. The global dispatcher patch is overridden by an explicit one.
  • DNS resolution itself. Proxyline tells the proxy a hostname; DNS-based exfiltration via the local resolver is out of scope.
  • Sockets opened before installProxyline ran. Existing keepalive connections continue to use whatever transport they were created with.
  • Module references captured before installProxyline ran. Anything that stored http.request in a local variable at import time keeps the un-patched reference.

For a process-wide proxy enforcement policy, combine Proxyline with operating-system level controls (egress firewall rules, network namespaces, seccomp, or a sidecar proxy).

#Install order matters

Install Proxyline as the first import in your application entry point. Anything that imports node:http, node:https, undici, or a wrapper library before Proxyline is initialized may have already captured the original method references. The patches still apply to future calls into http.request etc., but a stale captured reference will bypass them.

// entry.ts
import { installGlobalProxy } from "@openclaw/proxyline";

installGlobalProxy({ mode: "managed", proxyUrl: process.env.PROXY_URL! });

// only after install:
await import("./app.js");

#Process-wide singleton

Only one Proxyline runtime can be installed at a time. A second installProxyline call throws ProxylineError with code RUNTIME_ALREADY_ACTIVE. Call proxy.stop() to restore originals before installing a new runtime.

This is deliberate: two competing proxy patches would race on http.request and globalAgent, and the loser would silently bypass the winner.

#Credential handling

  • Userinfo in proxy URLs becomes a Proxy-Authorization: Basic header on every CONNECT / absolute-form request.
  • Userinfo, search, and fragment are stripped from any URL Proxyline reports back to the caller (handle.proxyUrl, decision.proxyUrl, runtime.installed).
  • redactProxyUrl is exported so callers can apply the same rule to URLs they log themselves.

#Threat model summary

ThreatMitigatedNotes
Library passes a direct http.Agent per requestyes (managed)Replaced before the request runs
Library passes a direct Dispatcher to fetchnoGlobal dispatcher is patched, explicit ones win
Library uses net.connect directlynoOut of scope
Library captured http.request at import timeno (if before install)Install Proxyline first
Environment variable set after installnoSnapshot at install time
Proxy credentials leaked into logsyes (in Proxyline output)Use redactProxyUrl for caller logs
Process-wide CA trust driftyesproxyTls is scoped to the proxy endpoint

#Reporting

Security issues: open a private advisory at https://github.com/openclaw/proxyline/security/advisories. Do not open public issues for unpatched problems.