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

Source: https://findproxyforurl.net/rules/ip-address-unusual-form/ · updated 2026-10-11

Changed 2026-10-11: New rule: an IP address written with leading zeros, in hex, as one number or in short form, or an IPv6 host with brackets, is read differently by the browsers, pactester and Windows; the rule explains why plain addresses are better even where the odd form works.

Rule PAC-C031 (`ip-address-unusual-form`), severity medium, category: 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).

## Bad

```js
function FindProxyForURL(url, host) {
  if (host == "010.001.002.003") {
    return "DIRECT";
  }
  return "PROXY 010.000.000.005:8080";
}
```

## Good

```js
function FindProxyForURL(url, host) {
  if (host == "10.1.2.3") {
    return "DIRECT";
  }
  return "PROXY 10.0.0.5:8080";
}
```

## Engine behaviour

- chromium: Passes 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. (source: lab, verified 2026-10-11)
- firefox: Same as Chromium for the host and for proxy addresses; isInNet reads leading zeros as decimal, dnsResolve as octal. (source: lab, verified 2026-10-11)
- pacparser: Passes the host as given; isInNet reads parts of up to three digits as decimal and resolves longer forms, dnsResolve reads leading zeros as octal. (source: lab, verified 2026-10-11)
- winhttp: Passes 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. (source: lab, verified 2026-10-11)
