Prisma Access Explicit Proxy PAC builder
Builds a PAC file for Prisma Access Explicit Proxy (<name>.proxy.prismaaccess.com:8080) with the Authentication Cache Service, identity-provider, FTP and private-address bypasses the PAC file guidelines require, plus the GlobalProtect domains when the agent runs alongside.
Palo Alto Networks’ sample PAC bypasses localhost and private addresses, FTP, the SAML provider and the Authentication Cache Service, then forwards to the proxy on port 8080. This builder keeps that order, resolves private ranges without a DNS lookup per request and adds the GlobalProtect domains when you select a coexistence mode.
Generated proxy.pac
[{"default":"example","help":"The subdomain you specified for the Explicit Proxy URL; the proxy listens on port 8080.","id":"proxy_name","label":"Explicit Proxy name","pattern":"^[a-z0-9-]+$","pattern_help":"lower-case letters, digits and hyphens (the part before .proxy.prismaaccess.com)","type":"text"},{"default":"okta","help":"The best practices say to bypass all SAML, Cloud Identity Engine and Authentication Cache Service URLs.","id":"idp","label":"SAML identity provider (must go direct)","options":[{"label":"Okta (okta.com, oktacdn.com)","value":"okta"},{"label":"Microsoft Entra ID (login.microsoftonline.com, aadcdn.msauth.net, aadcdn.msftauth.net)","value":"entra"},{"label":"Google Workspace (accounts.google.com, gstatic.com)","value":"google"},{"label":"Other (list the hosts below)","value":"none"}],"type":"select"},{"default":[],"help":"One per line; the domain and all its subdomains are matched.","id":"idp_domains","item_pattern":"^[a-z0-9-]+(\\.[a-z0-9-]+)+$","label":"Additional identity-provider or CIE domains that go direct","max":20,"pattern_help":"must be a domain such as login.idp.example","type":"list"},{"default":"none","help":"The portal and gateway names live under gpcloudservice.com; add your own portal name under internal domains if it is elsewhere.","id":"globalprotect","label":"GlobalProtect next to Explicit Proxy","options":[{"label":"No GlobalProtect","value":"none"},{"label":"GlobalProtect in Proxy mode (bypass *.gpcloudservice.com and *.prismaaccess.com)","value":"proxy"},{"label":"GlobalProtect in Tunnel and Proxy mode (also bypass *.rbi.io)","value":"tunnel_and_proxy"}],"type":"select"},{"default":["corp.example"],"help":"One per line, without a leading dot; the domain and all its subdomains are matched. Private apps reached through GlobalProtect belong here.","id":"internal_domains","item_pattern":"^[a-z0-9-]+(\\.[a-z0-9-]+)+$","label":"Internal DNS suffixes that go direct","max":50,"pattern_help":"must be a domain such as corp.example (no leading dot, no wildcard)","type":"list"},{"default":true,"help":"Uses an IP-literal test in front of isInNet, so host names never trigger a DNS lookup.","id":"bypass_private","label":"Plain hostnames and private (RFC 1918) addresses go direct","rules":["isinnet-on-hostname"],"type":"checkbox"},{"default":true,"help":"Explicit Proxy supports HTTP and HTTPS only; the sample PAC bypasses FTP.","id":"ftp_direct","label":"ftp:// URLs go direct","type":"checkbox"},{"default":false,"grade_note":"Lowers the grade unless \"Accept fail-open\" is ticked in the checker settings. The Prisma Access sample has no DIRECT fallback.","id":"direct_fallback","label":"Add \"; DIRECT\" after the proxy (fail open when it is unreachable)","rules":["direct-fallback-in-proxy-list"],"type":"checkbox"}]// proxy.pac for Prisma Access Explicit Proxy, generated by findproxyforurl.net
function FindProxyForURL(url, host) {
host = host.toLowerCase();
{{#if bypass_private}}
// plain hostnames (no dot) stay on the local network
if (isPlainHostName(host)) {
return "DIRECT";
}
// RFC 1918 and loopback addresses: literal IPs only, no DNS lookup for names
if (/^\d+\.\d+\.\d+\.\d+$/.test(host) &&
(isInNet(host, "10.0.0.0", "255.0.0.0") ||
isInNet(host, "172.16.0.0", "255.240.0.0") ||
isInNet(host, "192.168.0.0", "255.255.0.0") ||
isInNet(host, "127.0.0.0", "255.0.0.0"))) {
return "DIRECT";
}
{{/if}}
{{#if internal_domains}}
// internal domains and their subdomains go direct
if ({{#each internal_domains sep=" ||\n "}}dnsDomainIs(host, ".{{.}}"){{/each}}) {
return "DIRECT";
}
{{/if}}
{{#if ftp_direct}}
// Explicit Proxy supports HTTP and HTTPS only
if (url.substring(0, 4) == "ftp:") {
return "DIRECT";
}
{{/if}}
{{#if idp == "okta"}}
// SAML identity provider (Okta) must go direct
if (dnsDomainIs(host, ".okta.com") || dnsDomainIs(host, ".oktacdn.com")) {
return "DIRECT";
}
{{/if}}
{{#if idp == "entra"}}
// SAML identity provider (Microsoft Entra ID) must go direct
if (host == "login.microsoftonline.com" || host == "aadcdn.msauth.net" || host == "aadcdn.msftauth.net") {
return "DIRECT";
}
{{/if}}
{{#if idp == "google"}}
// SAML identity provider (Google Workspace) must go direct
if (host == "accounts.google.com" || dnsDomainIs(host, ".gstatic.com")) {
return "DIRECT";
}
{{/if}}
{{#if idp_domains}}
// identity provider / Cloud Identity Engine hosts must go direct
if ({{#each idp_domains sep=" ||\n "}}dnsDomainIs(host, ".{{.}}"){{/each}}) {
return "DIRECT";
}
{{/if}}
// Authentication Cache Service must go direct, otherwise SAML authentication loops
if (shExpMatch(host, "*.acs.prismaaccess.com")) {
return "DIRECT";
}
{{#if globalprotect == "proxy"}}
// GlobalProtect portal, gateways and Prisma Access services must not be proxied
if (shExpMatch(host, "*.gpcloudservice.com") || shExpMatch(host, "*.prismaaccess.com")) {
return "DIRECT";
}
{{/if}}
{{#if globalprotect == "tunnel_and_proxy"}}
// GlobalProtect portal, gateways, Prisma Access services and remote browser isolation must not be proxied
if (shExpMatch(host, "*.gpcloudservice.com") || shExpMatch(host, "*.prismaaccess.com") || shExpMatch(host, "*.rbi.io")) {
return "DIRECT";
}
{{/if}}
// default: everything else goes to Prisma Access Explicit Proxy (port 8080)
return "PROXY {{proxy_name}}.proxy.prismaaccess.com:8080{{#if direct_fallback}}; DIRECT{{/if}}";
}
Deploying it
Upload the file through a Forwarding Profile (Prisma Access hosts it) or on your own server. ASCII
only, 256 KB at most, IPv4 or domain names in PROXY statements. In GlobalProtect Tunnel and Proxy
mode, traffic this file returns DIRECT is still subject to the split-tunnel rules.
What the Prisma Access pack checks
Explicit Proxy listens on
<name>.proxy.prismaaccess.com:8080 and accepts HTTP and HTTPS only. The PAC
file (256 KB, ASCII, IPv4 or domain names in PROXY statements) must bypass the Authentication Cache
Service (*.acs.prismaaccess.com), the SAML identity provider, private addresses and FTP, otherwise
authentication loops or the traffic is dropped. With GlobalProtect in Proxy mode the app pushes the PAC
to the endpoint; in Tunnel and Proxy mode internet traffic follows the PAC while everything the PAC
returns DIRECT is still subject to the split-tunnel rules, and *.prismaaccess.com, *.gpcloudservice.com
and the portal and gateway names must be excluded from the proxy.- Port 8080; only IPv4 addresses or domain names in PROXY statements; ASCII; 256 KB maximum.
- Bypass SAML, Cloud Identity Engine and Authentication Cache Service URLs in the PAC.
- GlobalProtect coexistence: bypass *.prismaaccess.com, *.gpcloudservice.com (portal and gateways) and, in Tunnel and Proxy mode, *.rbi.io.
- URL filtering actions continue and override are not supported with Explicit Proxy.
- PAC-C029Prisma Access Explicit Proxy on a port other than 8080 high
- PAC-C030Prisma Access service domains not returned DIRECT info
- PAC-K019IPv6 address in a PROXY statement for Prisma Access high
- PAC-C022Identity provider not excluded from the SSE proxy medium
- PAC-C023Non-HTTP URLs reach a proxy that only accepts HTTP and HTTPS low
- PAC-C026Plain hostnames or private addresses are sent to the cloud proxy medium
- PAC-B014DIRECT in the PAC does not bypass the vendor's agent info
- PAC-B015Selected vendor pack, but the PAC never routes to that vendor info