Skip to main content

Documentation Index

Fetch the complete documentation index at: https://quintsecurity.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

Network Extension

The Quint Network Extension (com.quint.security.ne-extension) is a macOS NETransparentProxyProvider that sits in the network path and redirects outbound flows to specific LLM API hostnames into the daemon’s MITM pipeline. It is the sibling of the Endpoint Security extension and runs as its own system extension with its own entitlement.

Why it exists

The forward proxy can intercept any traffic if the client sets HTTP_PROXY / HTTPS_PROXY env vars. That’s fine for dev and servers, but real users won’t configure env vars in their IDE, their terminal, or every Electron app they run. The Network Extension solves that: once the user approves the extension, every outbound flow to a known LLM API host is routed through Quint automatically. No env vars, no CA trust dance, no per-app configuration. This matches how production EDRs (CrowdStrike, SentinelOne, Jamf Protect) operate on macOS.

What gets intercepted

The extension registers a hard-coded list of LLM API hosts in TransparentProxyProvider.buildNetworkRules. Only flows to these hosts reach handleNewFlow — everything else takes the OS default path, keeping overhead bounded.
CategoryHosts
Direct APIsapi.anthropic.com, api.openai.com, generativelanguage.googleapis.com, aiplatform.googleapis.com, api.mistral.ai
IDE agentsapi2.cursor.sh, api.codeium.com, copilot-proxy.githubusercontent.com, api.githubcopilot.com, api.tabnine.com, cody-gateway.sourcegraph.com
OSS providersapi.deepseek.com, api.groq.com, api.together.xyz, api.fireworks.ai, api.cohere.com, api.x.ai
AWS Bedrockbedrock-runtime.{region}.amazonaws.com
Azure OpenAI*.openai.azure.com
New hosts are added as customers request them. Browser chat UIs (claude.ai, chatgpt.com) are observed but not intercepted because they pin certificates.

Flow lifecycle

For each outbound TCP connection the kernel creates a flow and calls handleNewFlow(NEAppProxyTCPFlow):
  1. Extract PID from the flow’s audit token (macOS 15+). Flows without audit tokens are rejected.
  2. Self-mute the daemon. If the PID is the Quint daemon itself (from /etc/quint/daemon.pid), pass through — otherwise the daemon’s own cloud-forwarder traffic recurses through NE into itself.
  3. Resolve hostname via flow.remoteHostname (macOS 14+). Falls back to the resolved IP if DNS name isn’t available.
  4. Reject localhost127.0.0.1 / ::1 are daemon relay connections; intercepting them would create a loop.
  5. FlowFilter verdict:
    • .passthrough — return false, OS handles the flow normally
    • .observe — emit a metadata-only browser_chat event and pass through (for pinned-cert sites)
    • .intercept — proceed to the relay path
  6. Pre-check daemon reachability. If the relay port :9091 is unreachable, emit a daemon_down marker and pass through. The OS never blocks on us.
  7. Open the flow, relay bytes to the daemon over a dedicated unix socket. Daemon runs MITM in serveMITMImpl — the same pipeline as the explicit CONNECT path.

Relay protocol

The NE extension connects to the daemon on localhost port 9091. Each relay is a new TCP connection with this framing:
[ 4 bytes big-endian length ] [ JSON handshake ] [ raw app TCP bytes... ]
Handshake schema:
{
  "type":        "relay",
  "host":        "api.anthropic.com",
  "port":        443,
  "pid":         14661,
  "process_name": ""
}
After the handshake, the daemon:
  1. Allocates a flow-budget slot (backpressure — if 1000+ flows are already in-flight, closes the connection)
  2. Generates a leaf TLS cert for the target hostname via the local CA
  3. TLS-handshakes the relayed client as if it’s the target server
  4. Dials the real upstream with forced HTTP/1.1 ALPN
  5. Reads decrypted request → parses LLM body → extracts tool calls → forwards to upstream → re-chunks response → streams to client
See Forward Proxy → Streaming Responses for why SSE responses are always re-chunked regardless of upstream framing.

Backpressure guarantee

NE’s socket to the daemon is O_NONBLOCK. If the daemon is slow, paused, or crashed, the kernel send buffer fills and write() returns EAGAIN. A naive retry loop here would peg a CPU core — macOS’s cpu_resource watchdog SIGKILLs system extensions using >50% CPU over 180 seconds. NE enforces a per-frame 50 ms poll budget:
// On EAGAIN, poll(POLLOUT) with remaining budget.
// If poll times out, drop the frame and tear down the socket —
// next send attempts a fresh reconnect.
The contract: NE telemetry is lossy-at-the-edge. Under daemon backpressure, events are dropped rather than queued. The OS-level flow itself is always delivered — the extension never blocks the user’s network traffic behind the daemon. This keeps the extension alive under any load pattern and is the correct tradeoff for a kernel-adjacent component.
Earlier versions used if errno == EAGAIN { continue } which pegged CPU and was SIGKILL’d every ~90 seconds under load. See changelog v1.0.3 for the fix.

Installation & approval

NE requires two user-consent events:
  1. System extension approval — “QuintAgent” wants to activate QuintNetworkExtension. Handled in System Settings → General → Login Items & Extensions → Network Extensions.
  2. VPN configuration profile — grants the extension permission to redirect network flows. Installed by the container app (QuintAgent) via NETransparentProxyManager. No MDM required for single-user install.
Both approvals persist across reboots. The container app re-activates the tunnel on login via startVPNTunnel(options:).

Entitlement

The extension requires the com.apple.developer.networking.networkextension entitlement with content-filter-provider or transparent-proxy-provider capability. On dev builds without a production entitlement, macOS runs the extension in a restricted mode.

Relationship to ES

ES and NE are independent system extensions with separate bundles, entitlements, and approval flows. A failure in one does not affect the other.
ES extensionNE extension
FrameworkEndpointSecurityNetworkExtension
Entitlementcom.apple.developer.endpoint-security.clientcom.apple.developer.networking.networkextension
RoleProcess + file ground truthTransparent traffic redirection
InstallEndpoint Security Extensions approvalNetwork Extensions approval + VPN profile
Socket/var/lib/quint/es-events.sock127.0.0.1:9091
Failure modeExtension disabled, daemon keeps runningFlows pass through OS directly, no interception
Both feed the same daemon. The unisession.Tracker merges PID-level events from ES with content-level events from NE into a single session view.

Troubleshooting

See Operations → Troubleshooting for common NE issues:
  • Extension dies every ~90s (pre-v1.0.3 CPU watchdog kill — upgrade)
  • Duplicate installs stacked from swift build + xcodebuild mixing
  • [terminated waiting to uninstall on reboot] entries accumulating
  • NE process not starting after daemon restart