PAC-K013 · myipaddress-usage

Routing decided by myIpAddress()

medium · Compatibility across engines · Top 20 #19

Each engine chooses "the client's IP" by its own heuristic. With VPNs, Wi-Fi plus Ethernet, virtualisation adapters or IPv6, the answer differs between browsers and changes without a PAC re-fetch. Location-based routing keyed on it is unreliable.

Why it matters

myIpAddress() returns one address of a machine that usually has several. Chromium (since M72) probes which local address would be used to reach a public destination, falls back to resolving the machine’s hostname and then to routes into the private ranges, and returns 127.0.0.1 when all of that fails; before M72 it simply resolved the hostname. Firefox is reported to resolve the machine’s own hostname; WinHTTP is reported to return the first adapter in binding order. Three strategies, three possible answers on the same laptop, and none of them tracks a VPN connect/disconnect or a sleep/wake network change until the PAC is re-evaluated. A PAC that compares myIpAddress() against site ranges also has to handle the 127.0.0.1 failure value. Branch-office routing should use hostname patterns, DHCP-distributed per-site PAC URLs or the proxy’s own client-IP policy instead.

How to fix

Do not gate routing on myIpAddress(); distribute per-site PAC URLs or decide on the proxy by source address.

Examples

Bad

function FindProxyForURL(url, host) {
  if (isInNet(myIpAddress(), "192.168.0.0", "255.255.0.0")) {
    return "PROXY branch-proxy.corp.example:3128";
  }
  return "PROXY hq-proxy.corp.example:3128";
}
Open bad example in checker

Good

function FindProxyForURL(url, host) {
  return "PROXY proxy.corp.example:3128; PROXY backup.corp.example:3128";
}
Open good example in checker

Per-site routing is better handled by serving a different PAC per site (DHCP option 252 or GPO) than by inspecting the client address inside one PAC.

Engine behaviour

EngineBehaviourSource
chromium >=72Ordered heuristic: (1) source address of a route to 8.8.8.8 / 2001:4860:4860::8888, (2) first address from resolving the machine's hostname (IPv4 preferred), (3) route to 10.0.0.0 / 172.16.0.0 / 192.168.0.0 / fc00::; link-local and loopback only as last resort; returns 127.0.0.1 on failure. Before M72 it was just getaddrinfo(gethostname).doc, verified 2026-10-04 · ref
firefoxReported to resolve the local hostname (gethostbyname(gethostname())).expert, unverified
pacparserResolves the local hostname via getaddrinfo; a fixed value can be injected for tests.expert, unverified
winhttpReported to return the first adapter address in binding order.expert, unverified

Source: code = read in the engine's source, doc = vendor documentation, lab = observed in a lab run, expert = practitioner knowledge, not yet verified.

Related rules

References