Check your proxy.pac before your users do

A PAC file decides, for every request, whether traffic goes through your proxy or straight to the internet. Small mistakes route traffic around the proxy without anyone noticing. This site runs your PAC in Chromium, Firefox and pacparser engine profiles, explains every finding and grades the file from A+ to F.

Check a PAC file Browse the rules

Spot the 5 mistakes

This PAC looks reasonable and works in a quick test. It still has five problems that each send traffic past the proxy or slow every request down.

// proxy.pac - sample with 5 deliberate mistakes. Can you spot them?
function FindProxyForURL(url, host) {
  // internal servers go direct
  if (dnsDomainIs(host, "corp.example")) {
    return "DIRECT";
  }
  // partner portal is reachable without the proxy
  if (shExpMatch(url, "*partner.example.com*")) {
    return "DIRECT";
  }
  // private address space goes direct
  if (shExpMatch(host, "10.*")) {
    return "DIRECT";
  }
  if (isInNet(host, "192.168.0.0", "255.255.0.0")) {
    return "DIRECT";
  }
  if (shExpMatch(host, "*.example.net")) {
    return "PROXY proxy.corp.example:8080";
  }
}
Open this PAC in the checker

The mistakes

  1. Line 4: "corp.example" without a leading dot also matches evilcorp.example, so a look-alike domain bypasses the proxy. PAC-X003: dnsDomainIs pattern without a leading dot matches look-alike domains
  2. Line 8: shExpMatch on url instead of host: any URL with "partner.example.com" in its path or query string goes direct. PAC-C001: Hostname pattern applied to url instead of host
  3. Line 12: "10.*" is a text prefix, not a network. It matches the public host name 10.example.com and every 10.x name. PAC-X006: IP range matched as a text prefix
  4. Line 15: isInNet on a host name triggers a blocking DNS lookup for every request, and gives a different answer inside and outside the network. PAC-P002: isInNet called with a hostname
  5. Line 21: No unconditional return at the end: every other host gets undefined, which browsers treat as DIRECT. Traffic silently bypasses the proxy. PAC-X001: No unconditional return at the end of FindProxyForURL

What the checker does

  • Parses your file and runs it for your test URLs in each selected engine profile, inside a sandboxed worker in your browser.
  • Shows the result per URL and engine, which line decided it, and where engines disagree.
  • Rates the file A+ to F across errors, security, correctness, compatibility, performance and best practice.
  • Optionally checks delivery from pasted curl -sI headers.

Reference

A minimal correct PAC

function FindProxyForURL(url, host) {
  host = host.toLowerCase();
  // internal names and domains go direct
  if (isPlainHostName(host) || dnsDomainIs(host, ".corp.example")) {
    return "DIRECT";
  }
  // default route: always the last statement
  return "PROXY proxy1.corp.example:8080; PROXY proxy2.corp.example:8080";
}