PAC-C026 · sse-local-traffic-not-bypassed

Plain hostnames or private addresses are sent to the cloud proxy

medium · Correctness

Every vendor template returns DIRECT for plain hostnames and RFC 1918 addresses before the proxy statement. A cloud proxy cannot reach an intranet host; the request is denied or times out, and Skyhigh Client Proxy in explicit mode has no other place for these exceptions than the PAC.

Why it matters

Zscaler explains the failure mode: a request for an internal host that is proxied “first goes outside your network to the Zscaler proxy but is then blocked as it tries to access an internal host”. Its samples, Netskope’s template (isPlainHostName(host) first), Cloudflare’s templates (“No proxy for private (RFC 1918) IP addresses”, “Bypass plain hostnames”) and Palo Alto Networks’ sample (“Bypass localhost and Private IPs”) all put these two exclusions at the top. Skyhigh adds that in Client Proxy explicit mode “bypass rules are not applicable; instead, they must be configured via the PAC file”. The rule reports two things separately: no DIRECT branch for plain hostnames (isPlainHostName(host) or dnsDomainLevels(host) == 0), and no DIRECT branch for the private ranges (isInNet with 10/8, 172.16/12 or 192.168/16, or a regular expression or glob on the host string). Keep the IP-literal guard from PAC-P001 in front of isInNet, as the examples show. Zscaler’s App Profile PAC for Tunnel with Local Proxy mode is the one documented exception: there the Forwarding Profile PAC carries the bypasses and the App Profile PAC is a single return.

How to fix

Start the function with if (isPlainHostName(host)) return "DIRECT"; if (/^\d+\.\d+\.\d+\.\d+$/.test(host) && (isInNet(host, "10.0.0.0", "255.0.0.0") || isInNet(host, "172.16.0.0", "255.240.0.0") || isInNet(host, "192.168.0.0", "255.255.0.0"))) return "DIRECT";

Examples

Bad

function FindProxyForURL(url, host) {
  if (dnsDomainIs(host, ".corp.example")) {
    return "DIRECT";
  }
  return "PROXY ${GATEWAY}:80; PROXY ${SECONDARY_GATEWAY}:80";
}
Open bad example in checker

Good

function FindProxyForURL(url, host) {
  if (isPlainHostName(host) || dnsDomainIs(host, ".corp.example")) {
    return "DIRECT";
  }
  if (/^\d+\.\d+\.\d+\.\d+$/.test(host) &&
      (isInNet(host, "10.0.0.0", "255.0.0.0") ||
       isInNet(host, "172.16.0.0", "255.240.0.0") ||
       isInNet(host, "192.168.0.0", "255.255.0.0"))) {
    return "DIRECT";
  }
  return "PROXY ${GATEWAY}:80; PROXY ${SECONDARY_GATEWAY}:80";
}
Open good example in checker

All five vendor packs.

Related rules

References