Concept
Findings lifecycle and retest
How a finding is born, tracked, fixed and proven fixed, and why "Can't tell" is sometimes the right answer.
On this page
In one sentence: every finding has a stable ID that survives from run to run, so Pathwarden can tell you what's new, what's fixed and what came back, and can prove a fix with a retest.
A stable ID for every problem
Each finding has a finding ID, such as PW-003-39f2ede7c479090b: a hash of the rule and the objects that identify the problem. It stays the same for as long as the problem exists, whatever else changes in the domain. That makes it a reliable key for:
- Tickets. The ServiceNow and Jira plugins open, update, reopen and resolve tickets by finding ID.
- Accepted risks.
[[suppress]]matches a finding ID or a whole rule. - Retests.
pathwarden retest --finding PW-003-39f2ede7c479090b.
From run to run
pathwarden run is built for scheduled use. Each run compares its findings with the previous run in the run history and classifies each one:
| State | Meaning |
|---|---|
| New | First seen in this run. |
| Open | Still there. |
| Back | It was fixed in an earlier run, and it's back (regressed in the JSON). |
| Fixed | Gone: its domain was collected and the problem no longer exists (resolved in the JSON). |
| Accepted risk | Matched by an entry in [[suppress]], with a reason and an optional review date. |
| Can't tell | Its domain wasn't collected this time, the collection was much smaller than the last one, or it rests on sessions or local groups that this collection didn't read. Its absence proves nothing, so it stays open. |
The run history lives in a folder or a git repository you choose. At every level it keeps finding IDs, rules, severities and dates, plus each finding's title and domain. Titles name accounts ("SVC-ADSYNC@SCALE.LOCAL has a path to Tier Zero"). It can also keep full runs and share settings. Treat it like the report, or encrypt it with a passphrase.
Why "Can't tell" matters
A collection can fail halfway: a domain controller times out, a domain is left out, a password expires. The findings in what wasn't read then seem to disappear. Marking them fixed would close tickets for problems that still exist.
Pathwarden doesn't. If a run is missing domains, or has fewer than half the objects of the last one, findings in what wasn't collected are marked Can't tell (held in the run history's files) and stay open. A Quick collection, which reads the directory only, holds the findings and paths that rest on sessions or local administrator rights. The same applies to data sources such as SYSVOL, OpenGraph collectors and AzureHound: a finding that rests on a source that wasn't read in full is held, not resolved. A failed collection never closes a ticket.
Retest: proving a fix
After you change something, you don't have to wait for the next scheduled run. Retest checks chosen findings against a fresh collection and gives each a verdict:
- Fixed: its domain was collected and the finding is gone.
- Still open: with what changed, such as "exposure 61.0% → 12.0%" or "2 of 5 affected objects remain".
- Can't tell: the collection can't prove it either way: its domain wasn't in it, it's less than half the size of the baseline's, or it didn't read the sessions or local groups the finding may rest on.
Findings that weren't open before are listed as new, or back when they had been fixed.
# Collect again, then compare with the last scheduled run
pathwarden retest -i .\collect -c pathwarden.toml
# Or with an earlier collection, for one rule
pathwarden retest -i .\collect --baseline .\collect-before.zip --rule PW-003retest writes nothing unless you ask (--record), so it's safe to run any time. Its exit code is made for scripts: 0 every retested finding is fixed, 1 some are still open, 2 an error, 3 none are still open, but some are Can't tell.
One finding in seconds
In the app, each open finding in a run's report has a Retest button. pathwarden retest targeted --finding <ID> does the same from the command line. With the built-in collector, a targeted retest* re-reads only the objects the finding involves from Active Directory and answers in seconds: Fixed ✓, Still open with the specifics, or Can't tell with the reason.
When the finding rests on sessions or local administrator rights, the retest also reads the computers on its path, and only those: at most 50, over SMB and RPC, as your Windows account (on Windows) or with a user and password. That needs local administrator rights on them. A computer that can't be read makes the answer Can't tell, and the dialog names it and says why.
It has limits, which the dialog explains:
- It can't see a new path that avoids those objects. Collect again for that.
- It doesn't measure exposure again.
- Trust, AD CS and Privilege Zone findings, and findings with more than 500 objects, need a new collection.
Proving it to someone else
pathwarden evidence runs the same retest and writes a signed evidence pack: the verdicts, the history, and hashes of everything, that an auditor can verify without trusting the person who hands it over. See evidence packs.
Progress over time
Each run also records a history point: the accounts with an attack path to Tier Zero, exposure, Tier Zero protected, findings by severity and what changed. pathwarden history prints the trend, and the app's Progress page charts it.
References
- Pathwarden: Scheduled runs and retest
- Pathwarden: Retesting a finding in the app
- Pathwarden: Evidence packs
Very new and undergoing testing. These features haven't received a lot of testing yet. Try them out and let us know what's working.