PAC-C031 · ip-address-unusual-form

IP address written with leading zeros, in hex, as one number or in short form

medium · Correctness

Engines and people read 010.1.2.3, 0x0a.1.2.3, 167838211 or 10.1.2 differently. Even where the file works, such a form is confusing and leads to mistakes. Write IPv4 as four plain decimal numbers (10.1.2.3) and an IPv6 host in short form without brackets.

Why it matters

Most programs that read an IPv4 address accept more than four plain decimal numbers. A part with a leading zero is octal, so 010 means 8; a part starting with 0x is hex; and the last part may stand for several bytes, so 10.1.2 is 10.1.0.2 and 167838211 is 10.1.2.3. The PAC engines do not agree on these forms:

  • Chrome, Edge and Firefox convert the requested host to plain dotted form before they call FindProxyForURL. A test such as host == "010.1.2.3" or shExpMatch(host, "0x0a.1.2.3") never matches there, while pactester compares the text as written, so a test that gives pactester the host in the same form passes.
  • In isInNet(), Chrome, Edge, Firefox and pactester read a leading zero as decimal ("010.0.0.0" is 10.0.0.0), but dnsResolve() in the same engines reads it as octal (8.0.0.0), and so does isInNet() in Windows (WinHTTP), whose dnsResolve() returns such text unchanged. The same line can route differently on Windows.
  • A proxy written as PROXY 010.1.2.3:8080 is reached at 8.1.2.3 by the browsers and Windows, which is not the machine most readers would expect. A proxy address that is no valid address (192.0.2.300) is dropped by Chrome and Edge, and when it is the only entry they go DIRECT.
  • Chrome, Edge and Firefox pass an IPv6 host without brackets, in lower case and in short form (2001:db8::a), so host == "[2001:db8::a]" or "2001:db8:0::a" never matches there.

Even when an unusual form happens to work in every engine you use, it is bad practice. The next person who edits the file reads 010.1.2.3 as 10.1.2.3, copies it into a new rule or a firewall object, and gets a different address. Plain addresses can be searched, compared and checked; unusual forms hide mistakes. (lab, 2026-10-11)

How to fix

Write IPv4 addresses as four decimal numbers 0-255 without leading zeros (10.1.2.3) and IPv6 hosts in short lower-case form without brackets (2001:db8::a). Keep the brackets only in PROXY entries ([2001:db8::a]:8080).

Examples

Bad

function FindProxyForURL(url, host) {
  if (host == "010.001.002.003") {
    return "DIRECT";
  }
  return "PROXY 010.000.000.005:8080";
}
Open bad example in checker

Good

function FindProxyForURL(url, host) {
  if (host == "10.1.2.3") {
    return "DIRECT";
  }
  return "PROXY 10.0.0.5:8080";
}
Open good example in checker

Engine behaviour

EngineBehaviourSource
chromiumPasses the host in plain dotted form (192.000.002.010 arrives as 192.0.2.8) and IPv6 without brackets in short form; reads proxy addresses the same way; isInNet reads leading zeros as decimal, dnsResolve as octal; drops a proxy entry that is no valid address.lab, verified 2026-10-11
firefoxSame as Chromium for the host and for proxy addresses; isInNet reads leading zeros as decimal, dnsResolve as octal.lab, verified 2026-10-11
pacparserPasses the host as given; isInNet reads parts of up to three digits as decimal and resolves longer forms, dnsResolve reads leading zeros as octal.lab, verified 2026-10-11 · ref
winhttpPasses the host as written; reads leading zeros as octal in isInNet; dnsResolve returns address-like text unchanged; returns a proxy entry unchanged, and the Windows address lookup reads the forms like the browsers.lab, verified 2026-10-11

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