PAC-X010 · dnsresolve-compared-to-literal

dnsResolve result compared with a literal address

medium · Security and fail-safety

if (dnsResolve(host) == "10.1.2.3") depends on the resolver answering, answering fast and answering with exactly that record. Any failure makes the condition false and the request takes the default route unnoticed.

Why it matters

dnsResolve returns the address as a string, or an empty value (null or empty string, engine-dependent) when the name does not resolve. Comparing against a literal fails open: a resolver outage, a timeout, a second A record or a round-robin answer all produce “not equal”, and the request takes whatever the default route is. On a hostile network the resolver answer is attacker-controlled, so the decision is too. isInNet(dnsResolve(host), ...) shares the dependency but at least tolerates multiple addresses in the range; a hostname rule (host == "app.corp.example") has no DNS dependency at all.

How to fix

Decide on the hostname instead; if an address check is required, use isInNet on the resolved address with the whole subnet and order it after the string checks.

Examples

Bad

function FindProxyForURL(url, host) {
  if (dnsResolve(host) == "10.1.2.3") {
    return "DIRECT";
  }
  return "PROXY proxy.corp.example:8080";
}
Open bad example in checker

Good

function FindProxyForURL(url, host) {
  if (host == "app.corp.example" || dnsDomainIs(host, ".corp.example")) {
    return "DIRECT";
  }
  return "PROXY proxy.corp.example:8080";
}
Open good example in checker

Related rules

References