ZPA Part Four • Policies and Evaluation Order • Field Notes
Four things happen before anybody checks whether you are allowed. Knowing which four explains most of the confusing tickets in a ZPA deployment.
Where the last article stopped
Part Three ended on a deliberate hook. A broad wildcard segment does not only affect who can reach what. It affects which traffic ZPA considers its own in the first place, before any policy is evaluated at all.
That sentence needs unpacking, and unpacking it turns out to explain a whole category of behaviour that looks like a bug and is not. It also explains why a user with no entitlements whatsoever can resolve an internal hostname perfectly, and then be refused.
This article covers the two policies that govern a ZPA session, the order in which everything is actually evaluated, how to design access policies that are worth the migration, and the difference between the tunnel that belongs to a user and the tunnel that belongs to a machine.
Scope: this article is about managed devices connecting through the Client Connector. Privileged Remote Access and Browser Access for third parties and unmanaged devices follow different rules and deserve their own article. Examples are generalised, and several behaviours here were confirmed with Zscaler support during real implementations.
Part one
What happens, and in which order
1. Two policies, two different questions
A ZPA session is governed by two policy sets that are frequently confused, partly because both contain rules and both can block things.
Client Forwarding Policy: is this ZPA’s traffic at all?
This one runs on the client, and it runs first. It decides whether the Client Connector should treat a request as something ZPA handles, or leave it alone entirely. Its most important action is bypass: traffic matching a bypass rule never enters the ZPA path, is never matched against a segment, and is resolved and reached exactly as it would have been without ZPA installed.
This is the only lever that operates before everything else in this article. Remember that, because it becomes important later.
Access Policy: is this person allowed?
This one runs in the cloud, at connection time, and it answers the question the whole architecture exists for. It evaluates identity, group membership, device posture and context against segment groups, top down, and the first rule that matches wins. If nothing matches, the request is denied, because ZPA runs default deny.
Client forwarding policy decides whether ZPA is involved. Access policy decides whether you are allowed. They are not two layers of the same control.
2. The evaluation order, end to end
Here is what actually happens between a user typing a hostname and a session being permitted or refused.
Walk it slowly, because the ordering is the whole article.
The client forwarding policy is evaluated. If a bypass rule matches, everything stops here and the request behaves as though ZPA did not exist.
If there is no bypass, the Client Connector asks the broker whether the requested name matches an application segment. Any application segment, anywhere in the tenant. This is a question about configuration, not about the user.
If a segment matches, a synthetic address is returned. The client now holds an address in the 100.64.0.0/16 range and resolution has, from its point of view, succeeded.
The client attempts the connection. Only now does the question change from “what is this?” to “who is asking?”.
The access policy is evaluated, top down, first match wins — and the session is allowed or denied.
At the matching stage, ports are not evaluated and access policies are not evaluated. What counts is only whether an application segment exists that matches the requested name.
3. DNS matching is not an authorisation control
This is the consequence, and it is the single most misread behaviour in a ZPA deployment.
A user with no entitlement to an application will still resolve its hostname successfully. They will get a synthetic address back. They will conclude, reasonably, that the application exists and is available to them. And then the connection will fail.
Zscaler confirmed this directly during a support engagement: the presence of an application segment matching the requested name is sufficient for a synthetic address to be returned, regardless of whether the user is authorised. The entitlement check happens later, when the session is established.
A successful resolution is not a grant. It is only evidence that some segment, somewhere in the tenant, claims that name.
Two practical consequences follow. First, the service desk needs to know this, or every denied session becomes a DNS ticket. Second, and more seriously, it means the scope of a wildcard segment is larger than the scope of the policies attached to it.
What this does to a broad wildcard
A single segment containing *.example.com is enough for every hostname in that domain to be treated as internal and to receive a synthetic address, for every user, before any permission is consulted.
That includes hosts that were never meant to be published through ZPA. It includes names that should have continued to resolve through corporate DNS and be reached the way they always were. And it does not matter that no policy grants access to them, because the interception happens before policy.
This matters most in one specific project shape: enabling ZPA on the trusted network. When users are inside the corporate network and ZPA is active, a broad wildcard can capture traffic that has a perfectly good local path and did not need brokering at all. The risk is not a policy failure. It is unintended interception.
4. Three ways to stop it, and only one that fixes it
Bypass rules in the client forwarding policy. The only lever that operates earlier than the segment match, which is exactly why it works. It takes effect immediately and behaves predictably. It also creates a list of exceptions that somebody has to maintain, and exception lists grow in one direction only.
Reduce the wildcards. Replace broad domains with specific names, or with narrower patterns. This is the only option that removes the cause rather than the symptom, and the result is an architecture somebody can read later. It is also potentially a significant redesign, and it depends on discovery data existing in the first place — which is why the previous article spent so long on discovery.
Bypass on corporate network. During testing, segments configured with this bypass type were observed resolving to their real addresses rather than to synthetic ones while the client was on the internal network. That would make it a useful mechanism for exactly the trusted-network scenario described above: the logic stays inside ZPA rather than proliferating in forwarding exceptions.
That last behaviour was observed in a specific test, not confirmed as guaranteed. If a design is going to depend on it, validate it with Zscaler first rather than inferring it from an experiment.
Part two
Writing policies worth the migration
5. A policy that allows everything is a very expensive VPN
It is worth saying plainly, because it happens, and it usually happens for good reasons. The migration is behind schedule. Something broke. Somebody widened a rule on a Friday to unblock a department and the rule is still there.
If the end state is that every user reaches every segment, the organization has changed its architecture and not its security posture. It has replaced a VPN with a more sophisticated, better-instrumented, considerably more expensive VPN.
The minimum bar: identity, and then the device
Identity is the floor. Rules built on groups from the identity provider, one rule per purpose, so that access is expressed in terms somebody can review.
But identity alone answers only half the question. It establishes that somebody with these credentials is asking. It says nothing about what they are asking from, and credentials travel in ways devices do not.
Device posture is what closes that gap. A posture profile can verify that the request comes from a device the organization actually manages: a certificate issued by the internal certificate authority, membership of the on-premises domain, membership of the Entra tenant, and a range of other checks depending on what the estate supports.
Identity plus device posture turns “somebody with these credentials” into “this person, on a device we control”. For a managed-device deployment, that is where the bar should sit.
6. Divide by purpose, not only by resource
Part Three argued that segments should be designed by application rather than by subnet. There is a second cut that matters just as much, and it is the one people skip.
Take a file server. Users in a department need file access on port 445. Two or three engineers need administrative access to the same machine over remote desktop on 3389. Same hostname, same server, entirely different conversations.
Put both ports in one segment and you have made a decision without noticing it. The engineers need 3389, so the segment has to include 3389, so the policy that grants the department file access grants them remote desktop as well. The only policy you can write is the permissive one.
A resource is not a unit of access. What somebody does with it is.
The same logic applies well beyond file servers. Reading an application versus administering it. Using a database versus connecting to it with a management tool. Consuming an API versus deploying to the host that serves it. Wherever two audiences touch the same machine for different reasons, that is two segments.
7. The order of the rules is the policy
Access policy is evaluated top down and stops at the first rule that matches. Everything about how a policy set behaves follows from that one sentence.
The wildcard rule belongs last
If the tenant has both wildcard segments and specific ones — and during a migration it will — the rule that references the wildcard segment group goes at the bottom of the list. It is the umbrella that catches what discovery has not yet turned into a proper rule.
Place it higher and it matches first, every time, for everything. The specific rules underneath it become decoration: still configured, never evaluated, and quietly misleading anyone who reads the policy set later.
This also closes a loop from Part Three. When multimatch is enabled and two segments both match a request, neither of them wins on specificity. The rule order is what decides. So a policy set that looks wrong at the segment level is very often correct at the segment level and wrong here.
Default deny is true, and explicit denies are still worth writing
ZPA denies by default. Anything that reaches the bottom of the list without matching is refused. So why write a deny rule at all?
Because a default deny is silent, and a named deny is documentation. When a combination is known to be wrong — a group that must never reach an administrative segment, a population excluded by regulation, an application that a specific team is not permitted to touch — stating it explicitly at the top of the list records a decision.
Field note: the difference shows up in a review two years later. A default deny tells the reviewer nothing. An explicit deny tells them somebody considered this case and refused it, which is a different and much more useful piece of information.
8. Who decides who gets access, and it is not you
Discovery can tell you which FQDNs are in use and on which ports. It cannot tell you who is supposed to reach them. That information does not exist in any log.
The architect does not know it. The project engineer does not know it. What discovery produces is a record of who did access something, which is not the same as who should, and building policy on the first while calling it the second is how the entitlement drift described in Part Three gets carried forward into a brand new platform.
The people who know are the application owners. Or, more often and more honestly: the application owners are the people who have to find out.
What that conversation actually needs
- Every owner needs to understand what is being built, not just be asked to approve a list. An approval given without context is worth nothing at the review.
- Groups are the foundation. If the identity provider has no group that describes the intended audience, that gap has to be closed before the policy can express anything meaningful.
- Discovery data is the starting point for the conversation, not its conclusion. “These forty people accessed it last quarter” is a useful question, not an answer.
- Administrative access needs a separate conversation from ordinary use, because it usually has a different and much shorter list of names.
- Somebody has to own each answer, so that the next review has a person to ask.
This phase is where migrations quietly fail. Not through technical problems — through fatigue. The tempting shortcut is to widen the rules until the tickets stop, declare the migration complete, and move on.
It is worth resisting, because the opportunity does not come round twice. An organization changes its access model roughly once a decade. If this one ends with everybody reaching everything, the next honest attempt is years away and considerably harder to fund.
Laziness rewards attackers. Not dramatically, and not immediately — but a broad rule written on a difficult Friday outlives everybody who remembers why.
Part three
The tunnel with no user behind it
9. Machine tunnel: before anybody has logged in
Everything so far assumes a user. Somebody authenticated, with an identity, groups and a device posture. But there is a window before any of that exists, and some things genuinely have to happen inside it.
A device boots. No user has signed in. The Client Connector has no user identity to work with, so the ordinary ZPA tunnel cannot be established. Meanwhile the machine needs to reach a small number of internal services precisely so that a user can sign in.
The machine tunnel fills that gap. It is enrolled with its own machine provisioning key, the device belongs to a machine group rather than a user group, and it can reach the segments that machine group is authorised for — before any user is authenticated.
What genuinely belongs pre-login
The list should be uncomfortably short. In most environments it is three things.
Domain controller access. A client joined to an on-premises Active Directory domain has to reach the domain on the relevant ports before a user can authenticate against it. This is the canonical case, and for a remote domain-joined device it is the reason machine tunnels exist.
Endpoint management. So a device can be inventoried, patched and managed even when nobody has signed in for a while — which is exactly the machine you most want to reach.
Network access control services, where the device has to prove something about itself before it is allowed to proceed.
Everything else waits for the user. Business applications, file shares, collaboration tools, and above all administrative access: none of these has any business being reachable by a device with nobody behind it.
Every segment reachable before login is reachable by a machine with no person behind it. That is sometimes necessary and never free.
One configuration detail that catches people
Device posture profiles have a setting that controls whether they apply to the machine tunnel at all. If it is not enabled, the posture type is evaluated only for the user tunnels, and the machine tunnel proceeds without it.
The practical effect is a pre-login path that is less checked than the post-login one, in an environment where somebody believes both are covered. Worth verifying explicitly rather than assuming.
Field note: a useful pattern is a dedicated app profile for machine tunnel enrolment, and a machine group per provisioning key. It keeps the pre-login scope visible as its own thing rather than buried inside the general configuration.
Final thoughts
Most of what looks strange in a ZPA deployment comes from one place: the order in which things are evaluated is not the order people assume. Names resolve before anybody is authorised. Segments are matched before ports are considered. Rules are read top down and stop at the first one that fits.
None of that is hidden. It is just rarely stated in one place, which is why a user who cannot open an application raises a DNS ticket, and why a carefully written specific rule sits below a wildcard and never runs.
Segment matching decides which segments are candidates. Policy order decides which rule applies. Neither of them decides anything about who you are until step five.
The rest is the harder part, and it is not technical. Access policies are only as good as the conversations behind them, and those conversations happen with people who have other jobs, in a phase of the project where everybody is tired and the pressure to widen a rule is constant.
An organization changes its access model about once a decade. Ending up with a very expensive VPN is not a technical failure. It is what happens when the last twenty percent of the work gets traded for the last two weeks of the schedule.
Sources and references
- Zero Trust Navigator — Why ZPA Is Not Just a VPN Replacement (Part One)
- Zero Trust Navigator — How App Connectors Reach Private Applications (Part Two)
- Zero Trust Navigator — A Resource Nobody Declared Does Not Exist (Part Three)
- Zscaler Help — About Policies
- Zscaler Help — About Access Policy
- Zscaler Help — Configuring Access Policies
- Zscaler Help — About Client Forwarding Policy
- Zscaler Help — Configuring Client Forwarding Policies
- Zscaler Help — Configuring Bypass Settings
- Zscaler Help — Configuring Device Posture Profiles
- Zscaler Help — About Machine Groups
- Zscaler Help — Configuring Machine Provisioning Keys
- Zscaler Help — Deploying Machine Tunnels for Pre-Windows Login
- Zscaler Help — Using Application Segment Multimatch
- Zscaler Help — Configuring the Synthetic IP Range
- Figures 1 to 7: original Zero Trust Navigator diagrams.
The evaluation order and the behaviour of DNS matching described in sections two and three were confirmed with Zscaler support during a real implementation. The bypass on corporate network behaviour in section four was observed in testing and has not been confirmed as guaranteed. Product behaviour changes; verify against current documentation before relying on any of it in a design.