In ZAP's verification settings, what happens when a `loggedInRegex` misses, versus when a `loggedOutRegex` misses?
answer
- the two patterns are not mirror images
- three tests, in a fixed order
- one confirms, the other only vetoes
- absence of a logout marker means authenticated
- a second pattern can loosen the check
basics
~20 sThe two indicators are not mirror images. A logged-in pattern that fails to match produces a logged-out verdict and a re-login; a logged-out pattern that fails to match produces an unknown verdict, which the tool treats as still authenticated.
solid answer
~40 sThe check runs in a fixed order. If the logged-in pattern matches, the verdict is authenticated. Otherwise, if a logged-out pattern is configured and **does not** match, the verdict is recorded as `unknown` and still returns authenticated. Only if that last test falls through is the verdict negative. So a logged-in indicator fails **closed** — a miss means log in again — while a logged-out indicator fails **open**. The counter-intuitive consequence is that adding a logged-out pattern alongside an existing logged-in one **loosens** the check rather than tightening it: a page containing neither pattern used to be a logged-out verdict and now becomes `unknown`, which means authenticated.
go deeper
Configure the logged-in pattern first. It is the one that gives a real yes, and leaving it out is what makes an authenticated scan drift without warning.
Describe the three tests in order and say which verdict each one produces, including that a missing logged-out marker resolves to authenticated rather than to an error.
Explain why the asymmetry exists — a logged-out marker is a noisy veto, not a confirmation — and show that you would audit the unknown-state counter to catch a configuration that never confirms anything.
Set the house rule that a logged-in marker is mandatory and must be unrenderable anonymously, and make the counter distribution part of what a scanning pipeline reports rather than something a reviewer notices.
## The order matters more than the patterns A context's verification method holds two patterns, and it is natural to read them as symmetrical — one describes a logged-in page, one describes a logged-out page. They are not symmetrical. The check runs three tests in a fixed order, and the third is a fall-through: 1. Is a **logged-in** pattern configured and does it match? → verdict **authenticated**, counter `loggedin`. 2. Otherwise, is a **logged-out** pattern configured and does it **fail** to match? → verdict **authenticated**, counter `unknown`. 3. Otherwise → verdict **not authenticated**, counter `loggedout`. (There is a fourth case ahead of all three: if *neither* pattern is configured, the check returns authenticated immediately and records `noindicator`.) Test 2 is the surprise. Its logic is *I was told what logged-out looks like, I do not see it, therefore I have no evidence of a problem* — and *no evidence of a problem* is resolved as authenticated, not as an error. ## What each configuration actually does | configured | pattern present in the text | pattern absent | |---|---|---| | logged-in only | authenticated (`loggedin`) | **not authenticated** (`loggedout`) — re-login fires | | logged-out only | not authenticated (`loggedout`) | **authenticated** (`unknown`) | | both | logged-in wins if it matches | logged-out absent → authenticated (`unknown`) | Read the bottom row again. With both patterns configured, a response containing **neither** falls into test 2 and is treated as authenticated. With only the logged-in pattern configured, the same response falls through to test 3 and is treated as logged out. **Adding the second pattern changed a negative verdict into a positive one.** That is not a bug, but it is the opposite of what a reviewer assumes when they see two patterns where there was one, and it is why *more configuration* is not automatically *a stricter check* here. ## Why it is built this way The logged-out shape is the less reliable signal. An application shows its login form on a great many pages that are not in fact a logged-out session — an error page, a redirect target, a partial render. Treating every absence of the logged-out marker as a logout would produce constant spurious re-logins. Failing open on that test keeps a noisy signal from driving the expensive path. The cost is that the noisy signal cannot detect anything on its own. A logged-out pattern is a *veto*, not a *confirmation*. ## How to configure it - **Always configure a logged-in pattern.** It is the only one that produces a positive confirmation, and it is the only one whose failure mode is a re-login rather than a silent continuation. - Add a logged-out pattern **only** as a veto — to catch a specific interstitial such as a session-expired page that would otherwise still contain the logged-in marker. - Remember the match is a **search**, not a whole-string comparison, so a pattern hits anywhere in the header or body. A logged-in marker drawn from persistent site furniture — a navigation label that renders for anonymous visitors too, or a string that also appears in a bundled script — will match on a logged-out page and quietly confirm a session that no longer exists. - Prefer a marker that is **impossible to render anonymously**: an account identifier, a page only the authenticated route serves. ## The interaction with the strategy The asymmetry applies whatever strategy is selected, but the **text** the patterns run against changes, and that changes how often each test wins: - Under a **per-response** or **both** strategy, the patterns run against whatever the crawl fetched. Most of a crawl is not a page — it is assets, redirects and error bodies — and almost none of that contains either marker, so test 2 fires constantly and the `unknown` counter dominates. - Under a **polling** strategy, the patterns run against a response you deliberately chose, so a logged-in marker you picked for that page will match or genuinely fail. Test 2 fires far less often. - Under a **per-request** strategy, the patterns run against text the tool wrote itself, which rarely contains a server-rendered marker at all. That is a second reason to configure a positive indicator and to pick the poll strategy's endpoint deliberately: on the free strategies, *the weak test is the one that usually decides*. ## Checking the choice afterwards The verdicts are counted separately, which makes the configuration auditable. A run whose `unknown` count dominates is a run whose verification is resting entirely on test 2 — it has no positive confirmation of anything, and it will report authenticated whatever the target does short of rendering the exact logged-out marker. That is worth treating as a configuration defect even when the run looks clean.
- Why would adding a logged-out pattern to a working logged-in pattern make the check weaker?Because a response matching neither pattern changes category. With only the logged-in pattern it falls through to the negative verdict; with both, it satisfies the *logged-out marker is absent* test and is recorded as unknown, which returns authenticated. The extra configuration moved that case from negative to positive.
- What makes a good logged-in marker?Something the application cannot render for an anonymous visitor — an account name, a route that only exists once authenticated. Since the match is a search over header and body, a marker that also appears in site furniture, a script bundle, or a generic error page will confirm sessions that have already died.
- Which counter reveals that verification is resting on the weaker test?The unknown-state counter. It is incremented every time the verdict came from *the logged-out marker is absent* rather than from a positive match, so a run dominated by it has never actually confirmed an authenticated session, only failed to see evidence of a dead one.
saying these in an interview costs you the question
- Treats the two indicator patterns as mirror images
- Assumes a missing logged-out marker means log in again
- Says adding a second indicator always tightens the check
- Picks a logged-in marker that anonymous pages also render
- Thinks the unknown verdict stops the scan