The four browser adapters

On this page

  1. macOS
  2. iOS
  3. Linux
  4. Windows
  5. Responsibilities shared by all four
  6. Source references

This is the integration implemented in Outer Loop at the reviewed source revision. It is not a requirement to copy each adapter’s architecture or product policy.

Platform Browser engine Library host Web traffic Additional listener
macOS WKWebView Objective-C adapter in the XPC proxy service Authenticated HTTP/CONNECT, rewriting enabled by default Authenticated SOCKS for URLSession/outerframe networking
iOS WKWebView In-process Swift adapter calling C Authenticated HTTP/CONNECT Authenticated SOCKS for raw/native networking
Linux WebKitGTK 6 / GTK 4 In-process C adapter Authenticated HTTP proxy SOCKS is also started; HTTP forwards directly into SSH
Windows WebView2 / Win32 In-process C++ adapter Authenticated HTTP proxy None required by the current app

macOS

OuterSSHProxySession creates a context from its serial Dispatch queue, then a pool and both frontends. The same generated proxy credentials are used for HTTP and SOCKS. Its endpoint adapter carries two distinct listen ports. The browser process receives those values over XPC.

WKWebView uses ProxyConfiguration(httpCONNECTProxy:) on its website data store, applies credentials, and disables failover. The browser’s current code has a SOCKS fallback for an endpoint lacking the separate SOCKS-port field; that is adapter compatibility logic, not a second required web integration path.

macOS limits proxy matching with BrowserNetworkAddressPolicy.webProxyMatchDomains. Ordinary Internet traffic is not simply assumed to use SSH. An adopter must choose its own matching policy. Native URLSession/outerframe traffic uses the SOCKS port rather than passing through HTML rewriting.

Both frontends use the session pool supplied at creation. The browser selects a separate website-data store for the remote context. It injects the loopback compatibility script at document start. The adapter wires the detailed connection-failure and sudo-recovery handlers through its product interfaces.

XPC isolation and the allowlist of application commands accepted over XPC are Outer Loop policy. Embedding OuterSSH in another process does not automatically recreate that policy.

iOS

SSHProxyAsyncAdapter creates the pool and frontends in-process and bridges callbacks into Swift continuations. The adapter tracks consumers with leases. SOCKS leases use the library API; HTTP leases are managed in Swift.

WKWebView uses ProxyConfiguration(httpCONNECTProxy:), applies the proxy credentials, disables failover, and uses the selected website-data store. Native URLSession requests have their own SOCKS proxy configuration.

Separate storage and frontend instances distinguish servers. Each frontend is created with its session pool. iOS installs the shared Apple loopback compatibility script.

The adapter installs sudo recovery and socket availability. Unlike macOS’s session adapter, it does not currently install the detailed frontend connection-failure handler.

Linux

ConnectionFlows.c creates the context, pool, SOCKS listener, and HTTP listener. The HTTP listener reuses the generated credentials but forwards directly through the pool. Both frontends are created with that pool.

BrowserWindow.c creates a WebKit network session with data/cache directories for the saved server, sets a custom HTTP proxy, and supplies credentials through the authenticate signal. It checks that the challenge is for the configured proxy host/port and HTTP Basic, cancels retries, and does not save the proxy credentials.

The navigation handler translates http+unix and outerloop links before loading them. The current adapter injects session context but not Apple’s dynamic loopback compatibility script. It installs sudo recovery and availability notifications; it does not install the detailed connection-failure handler.

The Linux app currently accepts SSH host keys without a validator/prompt. This is that application’s policy, not an automatic trust policy required by OuterSSH.

Windows

BrowserProxy.cpp creates an HTTP frontend directly from the pool and generates its own proxy credentials and realm. Request-authority rewriting is enabled for Unix-socket and TCP aliases. HTML rewriting is disabled because literal localhost URLs use the proxy. It no longer needs to adapt HTTP traffic through a SOCKS connection.

The WebView2 environment is created with:

--proxy-server=http://127.0.0.1:<port>
--proxy-bypass-list=<-loopback>
--disable-quic
--force-webrtc-ip-handling-policy=disable_non_proxied_udp

The application supplies Basic credentials only when the challenge’s origin and realm match its own proxy. It uses a separate profile for the selected server. NavigationStarting and external-scheme handling translate product-specific navigation URLs into HTTP destinations.

Windows installs sudo recovery and availability handling, but not the detailed frontend connection-failure handler or the Apple loopback compatibility script. Its current pool configuration also omits a host-key validator. Proxy settings and these flags do not by themselves define a complete browser security policy.

Responsibilities shared by all four

All four adapters own server selection and secrets, marshal asynchronous results to their UI mechanism, translate socket addresses, provide bridge resources for the remote host, and arrange ordered destruction. All support Outer Shell navigation as application code rather than a special OuterSSH endpoint.

Changing the underlying web engine does not change endpoint encoding or allowlist enforcement. It does change how the host supplies proxy credentials, prevents bypass/fallback, isolates browser storage, intercepts custom navigation schemes, and presents recovery UI.

Source references