DIRECT in the PAC does not bypass the vendor's agent
info
With an SSE agent installed, the PAC is evaluated first by the application or OS, and the agent intercepts afterwards at the TCP or driver level. A DIRECT in the PAC therefore means "not through this proxy", not "not through the agent"; the destination also needs the agent's own bypass.
Why it matters
This is the interaction the vendor packs exist for. Zscaler: “Zscaler Client Connector intercepts any traffic heading to port 80 and port 443” in Tunnel mode, and domain bypasses must be configured in the App Profile PAC, IP bypasses as destination exclusions or VPN gateway bypasses. Netskope: the Client first connects directly and, with an on-premises proxy, “monitors for HTTP CONNECT requests”, resets matching connections and re-originates them through its tunnel. Skyhigh: “SCP can work with a PAC file without alterations”, forwards proxied requests when configured for the proxy port, and for sites the PAC sends direct “SCP is configured to bypass by port (80,443), or by destination IP, or by process”. Palo Alto Networks: the browser evaluates the PAC first, and GlobalProtect evaluates its split-tunnel rules for the rest. The finding is informational and appears when the PAC bypasses public destinations (or when you told the checker the PAC is distributed by an agent); it reminds you to mirror the exception in the agent’s configuration, where the vendor wants it.
How to fix
Mirror each public DIRECT destination in the agent's own bypass (ZCC app profile PAC / destination exclusions, Netskope steering exception, SCP bypass list, GlobalProtect split tunnel) or remove it from the PAC.
Examples
Bad
function FindProxyForURL(url, host) {
if (isPlainHostName(host)) {
return "DIRECT";
}
if (shExpMatch(host, "*.video-service.example.com")) {
return "DIRECT";
}
return "PROXY ${GATEWAY}:80; PROXY ${SECONDARY_GATEWAY}:80";
}
Open bad example in checkerGood
function FindProxyForURL(url, host) {
if (isPlainHostName(host) || dnsDomainIs(host, ".corp.example")) {
return "DIRECT";
}
return "PROXY ${GATEWAY}:80; PROXY ${SECONDARY_GATEWAY}:80";
}
Open good example in checkerRelated rules
- Long list of public hostnames routed around the proxy PAC-B008
- PAC sends traffic to a proxy the Netskope Client may not know PAC-B013
- Forwarding Profile and App Profile roles mixed in one Zscaler Client Connector PAC PAC-C020
References
- https://help.zscaler.com/zscaler-client-connector/best-practices-using-pac-files-zscaler-client-connector
- https://help.zscaler.com/zscaler-client-connector/best-practices-adding-bypasses-z-tunnel-2.0
- https://docs.netskope.com/en/netskope-client-network-configuration
- https://success.skyhighsecurity.com/docs/using-client-proxy-with-existing-pac-files
- https://docs.paloaltonetworks.com/prisma-access/administration/prisma-access-mobile-users/mobile-users-explicit-proxy/use-explicit-proxy-with-globalprotect-or-a-third-party-vpn/explicit-proxy-and-globalprotect-set-it-up