## TL;DR
A naive diff compares raw output rows, so any changed banner, patched version string, or reordered service makes the old row vanish and a new row appear, reported as a brand-new vulnerability. Diff on the stable identity of a finding, check, host, and location, and classify each difference as new, resolved, changed, or unchanged, with changed items shown as changes, never as fresh criticals.

```text
agent's scan diff flagged config changes as new vulnerabilities
```

## Use this when
- A scan diff lists new vulnerabilities that, on inspection, are the same services with updated versions or banners.
- Resolved counts and new counts are both implausibly high between two scans of the same authorized scope.

## Not for this skill when
- The environment genuinely changed wholesale, such as a rebuilt server. A human should review that diff; classification rules assume continuity.
- The two scans used different tool versions or template sets. Note that as a diff caveat before blaming identity matching.

## Steps
1. Take one flagged new item and find its counterpart in the earlier scan by hand, identifying what raw field changed, such as a version string in the evidence. Verify: Verify: the change is a field difference inside the same check and location, named explicitly.
2. Define the diff identity as check id plus host plus location, with evidence treated as an attribute that can change, and write the classification rules for new, resolved, and changed. Verify: Verify: the rules decide the hand-worked example as changed, not new.
3. Re-run the diff with those rules and compare category counts against the naive diff. Verify: Verify: new and resolved counts fall to plausible numbers and the changed category holds the rest.
4. Render changed items with a short what-changed note drawn from the differing fields, so a version bump reads as a version bump. Verify: Verify: a reader can see why each changed item was classified that way.
5. Add golden tests: a pair of small scan files with a known banner change, a true new finding, and a true resolution, asserting the diff classifies all three correctly. Verify: Verify: the tests pass and would fail under raw-row diffing.

## Variant phrasings
### scan diff version change flagged new vulnerability
The symptom phrasing.
### diff findings by identity check host location classify changed
The design phrasing.
### pentest scan comparison false new resolved counts inflated
The counts phrasing.

Compatibility: Compatibility: any agent diffing workflow over scanner exports; identity fields must be extracted identically from both scans.

## Why it happens
Scanners describe the present, including incidental details like banners and build strings that change for innocent reasons, patching most of all. Row-level diffing cannot tell a changed description from a changed reality, so routine maintenance becomes a flood of new and resolved pairs. Identity-based diffing encodes what a finding is, separately from how it was described on the day.

## Edge cases / pitfalls
- A version change can itself resolve or introduce a real vulnerability; classification as changed should trigger a re-evaluation of that finding, not a free pass.
- Tool or template updates between scans change descriptions en masse; pin tool versions per engagement or annotate the diff with the version change.
- Keep the naive counts out of client reports entirely once you have seen them mislead; publish only the classified diff.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_QFPPxt9gg2a_auKLdPoyew
