Scanner guide18 min read

Scanner Output Diff and Change Event Generation

The Monday scan against a production application emits 312 findings across nine modules. The Tuesday scan against the same application emits 287 findings across the same nine modules. The leadership question that lands at the standup is whether the twenty-five finding delta is engineering closing twenty-five issues, the authenticated module losing its session and missing thirty findings while five new ones land, overrides expiring on twelve previously suppressed items, or a release that retired a subsystem and removed eighteen findings while creating eight new ones in its replacement. The delta alone is unanswerable; the per-finding change event stream is the record that answers it. This guide covers the scanner-side mechanic that converts two scan executions against the same target into a typed event stream on the per-finding identity, the deterministic identity match key that keeps the stream reproducible across cycles, the seven event types the diff emits, the coverage signature the diff reads alongside the event classification, how the diff interacts with the override register and the SLA clock, seven failure modes, how imported third-party output joins the surface, and how ISO 27001, SOC 2, PCI DSS, NIST SP 800-53, NIST CSF 2.0, DORA, and NIS2 read the change event chain.

The change event stream sits underneath the baseline-and-trend metric layer and feeds the activity log, the remediation routing rule, the audit chain, and the leadership reporting view. It is not a chart; it is the durable per-event record the chart reads against. The discipline matters because the same disappearance can be remediation, coverage drift, override suppression, or scope change, and the event type written determines whether the leadership conversation lands on closed work, lost coverage, controlled exception, or surface change.

What the diff is and what it is not

The diff is a per-cycle mechanic that reads scan-N output against scan-N-1 output for the same target and writes a typed event per finding identity that crossed a boundary between the two scans. The diff does not emit a single aggregate number; it emits a stream of discrete events on the row level, with each event carrying the finding identity, the prior state, the new state, the event type, the contributing inputs, and the activity log entry that records the transition.

The diff is not the baseline-and-trend metric layer. The scan baseline and trend comparison guide covers the aggregate metric layer that reads many change events across a window and produces programme-level signal (open finding count per severity at cycle close, inflow rate per cycle, fix rate per cycle, coverage stability). The trend reads the change event stream; the change event stream is the source data. The two disciplines compose but operate on different layers, and a trend without a defensible change event stream underneath is a chart that moves unpredictably.

The diff is not the recurring detection identity discipline either. The scanner finding aging and staleness guide covers the first_seen and last_seen lifecycle of a recurring identity. The diff consumes the recurring identity as a stable match key and writes events when the identity crosses a boundary between two scans; the aging discipline reads the historical identity record. The boundary matters because programmes that conflate the two end up either resetting aging counters on every diff cycle or treating unchanged findings as fresh.

The deterministic identity match key

The diff reads scan-N against scan-N-1 through a composite identity key of module identifier plus per-tool finding identifier within the module output. The composite key is stable across runs of the same module against the same target as long as the module emits the same finding identifier for the same underlying condition.

Key componentWhat it namesStability characteristic
Module identifierScanner module that emitted the finding (SSL, headers, tech fingerprint, Semgrep ruleset, Nessus plugin family, Burp issue type, imported source identifier).Stable across runs; recorded against each finding output.
Per-tool finding identifierStable identifier the module emits for the same condition (Nessus plugin id, Burp issue id, Semgrep rule id, internal module finding id).Stable across runs of the same module pack version; drifts on rule pack updates that retire or rename rules.
Target referenceThe asset the scan executed against (domain, host, repository, container image, code-scanner project).Stable across runs; the diff is always per-target.
Composite (module::finding_id)The full match key the diff reads against (module identifier plus per-tool finding identifier).Reproducible across audit reads of the same two scan executions.

The composite key discipline is what lets the change event stream be reproducible across audits and across leadership cycles. Programmes that match findings by free-text title across cycles cannot produce a defensible diff because the title text drifts when scanners ship rule pack updates that rephrase descriptions; the apparent new-finding rate spikes after every rule pack revision even though no new condition was detected. The composite key reads against the structured identifier the module emits and ignores the human description.

Seven event types the diff emits

Seven event types cover most of the per-cycle movement that surfaces in practice. Each event type carries a different audit reading and a different downstream routing path.

New

Finding identity is present in scan-N and absent from scan-N-1 and the asset was reached at compatible coverage. The triage path is whether the finding is a new exposure, a regression of a previously closed item, a finding the prior scan missed because of coverage drift, or a finding the prior scan missed because the rule pack changed. The SLA clock starts at the new finding identity is creation timestamp.

Reopened

Finding identity reappears after a prior closure cycle. The reopen event reads the historical record and notes that the override or the resolution did not hold. The SLA clock reads against the original detection moment with the reopen recorded as a state transition; the trend layer reads both the original open duration and the reopen interval. A reopened event is a stronger signal than a new event because it indicates a verification or remediation failure.

Regressed

Finding identity is present in both scans but the severity, status, or evidence moved unfavourably. Typical causes are an EPSS-driven priority refresh that landed during the cycle, a CVE base-score revision that increased the workspace severity, an authentication scope change that exposed the finding to higher-criticality assets, or a control change that increased the blast radius. The activity log records the prior-to-new transition and the regressed event references the contributing input (the EPSS feed date, the NVD revision id, the control change identifier).

Resolved

Finding identity is present in scan-N-1 and absent from scan-N and the coverage signature confirms the asset, route, and authentication state were reached at parity with the prior scan. Resolved events still need a verification step (a targeted retest) before the workspace marks the finding closed. The SLA clock closes at the resolved event timestamp; the workspace can still surface the closed-and-reopened state if a later cycle fires a reopened event against the same identity.

Suppressed

A finding identity that the prior scan carried as visible is now silenced by an override. The change event records the override identifier, the scope, the cited reason, and the named approver so the audit chain reads the suppression as a controlled state change rather than as a vanishing finding. The SLA clock suspends until the override expires or is revoked.

Coverage-dropped

Finding identity vanished but the coverage signature shows the scan did not reach the asset, the route, the authentication state, or the module the prior scan exercised. The coverage-dropped event is reported separately from resolved so the trend layer does not conflate coverage loss with remediation. The downstream remediation router does not close the underlying finding; the workspace surfaces the coverage gap for repair before the next cycle.

Scope-changed

Finding identity left the comparison set because the target moved out of scope. The event records the prior scope, the new scope, and the reason for the move (decommission, scope reduction, ownership transfer, scope split into multiple engagements). The audit chain reads the scope-changed event as a controlled state change rather than as a vanishing finding.

The coverage signature read

A finding disappearing from scan-N relative to scan-N-1 is not the same operational state as a finding genuinely closed by remediation. The diff cannot distinguish remediation from coverage drift without reading the coverage signature alongside the event stream.

Coverage signature fields

  • Which modules ran on scan-N versus scan-N-1
  • Which modules timed out on either scan
  • Which authentication state the scanner reached
  • Which routes the scanner did not exercise
  • Which rate-limit or throttle constraints applied
  • Which credential rotation events occurred between cycles
  • Which target re-validation events occurred between cycles

How the diff uses the signature

  • Disappearance with coverage parity classifies as resolved.
  • Disappearance with coverage loss classifies as coverage-dropped.
  • Module unique to one scan generates a modules_only_in_a or modules_only_in_b classification at the module-level coverage gap.
  • Authentication state delta is annotated on every event in the affected scope.
  • The activity log records the coverage signature reference alongside each event.

For the upstream authentication discipline that produces the authentication-state part of the coverage signature, the scanner authentication failure modes guide covers the patterns that produce coverage drift dressed up as remediation. For the module-level recovery side, the scanner module failure and partial scan recovery guide covers what happens when a module times out or partially completes.

How the diff interacts with the override register

The finding overrides register holds the workspace decisions that change a finding is operating disposition: false-positive overrides, accepted-risk overrides, manual severity adjustments, and deferrals. The diff reads the override register before classifying the event so an override-held finding produces the right event type.

Override applied between scans (suppressed event)

A finding the prior scan carried as visible now reads against an active override. The diff fires a suppressed event rather than a resolved event; the activity log records the override identifier and the scope so the audit chain reads the suppression as a controlled state change.

Override expired between scans (reopened event)

A finding under an accepted-risk override that has expired since the prior scan surfaces in the current scan. The diff fires a reopened event annotated with the expired override identifier and the reason for the expiry; the workspace surfaces the finding for remediation against the original detection clock.

Severity-override held during severity refresh (regressed event)

A finding under a manual-severity-override that the prior scan carried at one priority is now refreshed at a different priority by the recalculation. The diff fires a regressed or improved event annotated with the override-held workspace severity so the operating workflow reads the right disposition.

False-positive override during scan disappearance (suppressed event)

A finding that the prior scan carried as visible and a false-positive override now silences fires a suppressed event. The diff does not classify the disappearance as resolved; the workspace continues to read the finding under the override-held disposition.

For the override lifecycle (active, review-due, in-review, renewed, expired, revoked) and the closed-loop renewal record, the scanner finding exception lifecycle and expiry guide covers the operating discipline that produces the override-state record the diff reads against.

How the diff interacts with the SLA clock

The SLA clock starts at the finding-created timestamp and bounds how long a finding can carry an open status before it breaches the workspace severity-tier SLA. The diff event type determines how the clock reads against the event.

New event

Starts a fresh SLA clock at the new finding identity is creation timestamp.

Reopened event

Reads against the original detection moment with the reopen recorded as a state transition. The trend layer reads both the original open duration and the reopen interval.

Regressed event

The clock continues against the original detection moment; the severity move is annotated on the activity log entry but the clock does not reset.

Resolved event

Closes the clock at the resolved event timestamp. The workspace can surface the closed-and-reopened state if a later cycle reopens the same identity.

Suppressed event

Suspends the clock until the override expires or is revoked. The activity log records the suspension and the override scope.

Coverage-dropped event

The clock continues; the workspace does not close the underlying finding. The coverage gap is surfaced for repair so the next cycle reads compatible coverage.

For the SLA workflow side that consumes the change event clock interactions, the vulnerability SLA management use case covers the operating mechanism that pairs the diff discipline to the severity-tier expectations.

Seven failure modes that break the change event stream

Seven failure modes cover most of what surfaces at fieldwork as a change event chain that cannot be reproduced. Each one collapses the per-finding identity discipline into a state where the operating record and the historical record disagree silently.

Free-text identity matching across scans

The diff matches findings by title text rather than by the composite module-plus-finding-id key. When the scanner ships a rule pack update that rephrases descriptions, the match breaks and the diff produces noise events that do not correspond to real movement. The apparent new-finding rate spikes after every rule pack revision.

Missing coverage signature read

The diff classifies disappearances as resolved without checking whether the new scan reached the asset at parity with the prior scan. The resolved bucket fills with coverage-dropped findings and the trend overstates fix throughput.

Override register skipped before classification

Suppressed findings reopen noisily every cycle or vanish silently when the override is applied; the suppression history is lost. The leadership view surfaces accepted-risk findings as new every cycle.

SLA clock reset on every diff event

The clock starts from the diff event timestamp instead of from the finding-created timestamp. The how-long-has-this-finding-been-open reading no longer matches the detection date and the SLA breach record loses meaning.

Change event without activity log entry

The classification runs in place without writing the event record. The auditor sees only the current finding state and cannot reconstruct how it was reached or which scan execution produced the event.

Inconsistent diff scope

The diff runs against some module outputs but not others, typically caused by stale module enumeration or missing-module placeholders. The change event stream has gaps that surface as silent disappearance for the missing modules.

Missing input version stamp

The change event omits the scan execution identifiers, the module identifiers, the rule pack version, or the coverage signature reference. The audit chain cannot reproduce the diff against the inputs of the moment and the framework reading around show-me-the-evidence-the-diff-is-defensible lacks anchor data.

Imported third-party output and the change event stream

Imported findings from Nessus, Burp Suite, CSPM exports, CSV imports, container scanner outputs, and consultancy deliverables join the change event surface through the same per-finding identity that the native scanner output produces. The import workflow records the source-emitted vendor identifier on the evidence section, joins the import to a scan execution record so the diff has a comparison anchor, and preserves the source artefact in document management so the at-detection vendor severity reads from the original input file.

For the structural intake mechanics, the importing third-party scanner results guide covers the import workflow that lands the per-finding identity the diff reads against. For the cross-tool merge surface that decides whether two findings from different classes describe the same condition, the scanner finding merge across targets guide covers the cluster identity discipline that the diff reads alongside the per-source change events.

The honest scope is that the diff cannot match an imported finding from one third-party tool against a native finding from a different scanner class without an explicit cross-tool dedup decision. The diff reads each source class independently and produces a per-class change event stream; the cross-class merge decision lives in the merge surface that the diff reads against, not in the diff itself.

How compliance frameworks read the change event chain

Auditors read the change event stream as the durable record of how the open finding inventory moved across the audit observation window. The framework readings below cover the controls that most often land on the change event discipline at scoped fieldwork.

FrameworkControls that read the change event evidence
ISO 27001:2022Annex A 8.8 technical vulnerability management (per-cycle reconciliation evidence with new, reopened, regressed, and resolved events on the per-finding identity); Annex A 8.16 monitoring activities (change event stream as a monitored operating record); Annex A 5.23 information security for use of cloud services (change events on cloud-target scans).
SOC 2 (TSC 2017)CC7.1 detection of security events (detection events tracked through the lifecycle with named state transitions); CC7.2 system operations (cycle-to-cycle operating evidence); CC4.1 monitoring activities (change event stream as part of the monitoring artefact chain).
PCI DSS v4.0Requirement 11.3 internal and external vulnerability scans (per-cycle scan output with documented cycle-to-cycle movement at the per-finding level); Requirement 6.3.1 vulnerability identification and rating (regressed event annotation as part of the priority-rating discipline); Requirement 6.3.2 inventory of bespoke software (resolved and new events on per-asset scan output).
NIST SP 800-53 r5RA-5 vulnerability monitoring (cycle-to-cycle monitoring records with structured event types); SI-2 flaw remediation (resolved and reopened events as part of the flaw response discipline); CA-7 continuous monitoring (change event stream as part of the continuous monitoring evidence).
NIST CSF 2.0DE.CM continuous monitoring (detection events reconciled across cycles); DE.AE adverse event analysis (reopened and regressed events as adverse-event signal); RS.AN response analysis (change event stream feeds the response lifecycle); ID.RA risk assessment (change event evidence reads as part of the risk-input current-state chain).
DORAArticle 9 protection and prevention (workspace records the ICT risk surface across cycles); Article 17 ICT-related incident management (incident reconstruction reads the change event stream); Article 24 testing of ICT tools and systems (per-cycle testing evidence reads through the change event record).
NIS2Article 21 risk management measures (risk-treatment activity captured per cycle); Article 23 incident reporting (incident evidence chain reads the change event history).

How SecPortal supports diff and change event generation

SecPortal stores each scan execution as a row that carries the target, the scanner class, the module set that ran, the result summary with structured findings per module, the scan timestamp, and the engagement reference. The platform exposes the structured records the change event stream operates against.

Workspace-scoped diff endpoint

The platform exposes /api/scans/diff?scan_a=&scan_b= as a workspace-scoped read that returns the per-finding new, fixed, and unchanged buckets against the composite module-plus-finding-id key, plus the modules_only_in_a and modules_only_in_b lists that surface the module-level coverage gap so coverage drift is interpretable, and annotates each finding entry with the active override type. The endpoint is the building block the change event classification reads against; the workspace then writes the event type back through the structured update surface. The scan-to-scan diff feature covers the API contract, the response schema, and the override annotation states the diff returns.

Per-finding identity preserved across cycles

The same workspace plus template plus asset reference match key carries the finding identity across recurring scans, so the diff reads and writes against a stable identity rather than against per-cycle finding rows. The findings management feature covers the per-finding record the diff operates against.

Override register read before classification

Finding overrides record cited reason, named approver, scope, and hard expiry on the per-finding identity. The diff endpoint annotates each entry with the active override type and the change event classification reads the override register so suppressed and regressed events read the override-held disposition. The finding overrides feature covers the override mechanism.

Activity log captures the change event stream

The activity log writes every per-finding event with the named actor, the timestamp, the engagement reference, and the prior-to-new state transition. CSV export is available for evidence packaging. The change event stream writes event records through the activity log so the audit chain reads diff events alongside creation, assignment, status, override, and retest events. The activity log feature covers the audit-trail mechanism.

Bulk import joins the change event surface

Bulk finding import preserves the source artefact alongside the workspace-translated rows so imported third-party output joins the change event stream through the same per-finding identity discipline. The diff reads the imported finding identity through the import-source-plus-per-tool key and produces per-source events. The bulk finding import feature covers the import surface.

Continuous monitoring produces the cycle cadence

Continuous monitoring runs scheduled scan executions on daily, weekly, biweekly, or monthly cadence so the change event stream is produced on the cycle the workspace operates. The continuous monitoring feature covers the recurring scan cadence.

Compliance tracking holds the framework crosswalk

The compliance crosswalk records which framework controls read the change event evidence at audit fieldwork. The compliance tracking feature covers the framework reading surface.

Honest scope: SecPortal does not currently ship a packaged scheduled job that auto-classifies coverage-dropped versus resolved events at the cycle close, a packaged scheduled job that auto-writes change event types to the activity log on each scan execution, or a packaged real-time webhook delivery that pushes change events to external systems. Programmes typically run the classification as a scheduled workspace job operated against the diff endpoint that reads the new/fixed/unchanged buckets, joins them against the coverage signature and the override register, and writes the event type back through the structured update surface with each classification captured in the activity log. SecPortal does not ship packaged Jira, ServiceNow, Slack, PagerDuty, SIEM, or SOAR change-event-push connectors; the engagement record holds the durable change event stream and external systems hold engineering execution detail.

An operational checklist

When designing the diff match key

  • The composite identity key is module identifier plus per-tool finding identifier; never the free-text title or the human description.
  • The per-tool finding identifier is the stable identifier the module emits for the same condition (Nessus plugin id, Burp issue id, Semgrep rule id, internal module finding id).
  • The target reference is recorded on the scan execution and the diff is always per-target.
  • The composite key is reproducible across audit reads of the same two scan executions.

When classifying each event

  • The diff reads the override register before classifying so suppressed and regressed events read the override-held disposition.
  • Disappearance is classified as resolved only when the coverage signature confirms parity; otherwise the event classifies as coverage-dropped.
  • Reappearance is classified as reopened against the historical finding identity; the SLA clock continues against the original detection moment.
  • Severity or status move on the same identity classifies as regressed (unfavourable) or improved (favourable); the contributing input is annotated on the event.
  • Scope move classifies as scope-changed with the prior scope, the new scope, and the reason recorded.

At event-write time

  • The activity log entry is written with the scan execution identifiers, the module identifier, the per-tool finding identifier, the event type, the prior state, the new state, the coverage signature reference, the override register reference, and the actor or scheduled job.
  • The SLA clock reads according to the event type: new starts fresh, reopened reads original detection, regressed continues, resolved closes, suppressed suspends, coverage-dropped continues, scope-changed exits.
  • The change event references the input version stamp (rule pack version, EPSS feed date, KEV catalogue revision, asset criticality version) so the audit chain can reproduce the classification against the inputs of the moment.

At cycle review

  • A weekly or monthly review reconciles the change event stream against the expected cycle volume; the review flags coverage-dropped events as repair work before the next cycle.
  • The review samples reopened events and confirms the historical finding identity is the same one the workspace closed; the review samples regressed events and confirms the contributing input is recorded.
  • The review reads the change event stream alongside the override register so accepted-risk and false-positive holds remain consistent with the change events the diff produced.
  • The review decisions are captured in the activity log so the audit chain reads diff maintenance as a controlled operating activity.

Where this fits in the wider scanner evidence chain

Diff and change event generation sit next to several adjacent scanner-side disciplines that read or write to the same per-finding identity. The discipline composes with each and reads alongside them in the audit conversation.

For the cycle-to-cycle metric movement that reads the change event stream at the programme-shape level, the scan baseline and trend comparison guide covers the aggregate metric layer that sits above the per-finding diff. For the structural evidence chain from scan execution to closed finding that the diff event stream writes into, the scanner evidence chain guide covers the end-to-end chain the change events feed.

For the after-intake priority refresh that produces regressed events when an upstream signal moves, the scanner finding priority recalculation after import guide covers the recalculation discipline. For the integrity discipline that makes the two scan executions verifiable as unchanged after the fact, the scanner output attestation and chain of custody guide covers the canonical record the diff reads against.

For the reproducibility discipline that lets the original analysis be replayed from archived inputs, the scanner output replay from archived inputs guide covers the per-execution and per-job records the diff reads against when an audit reads a prior change event. For the recurring-detection freshness discipline that reads first_seen and last_seen, the scanner finding aging and staleness guide covers the aging surface that reads the same per-finding identity the diff operates against.

Scope and limitations

The diff only produces a defensible change event stream when the per-finding identity is stable across cycles, when the coverage signature is recorded alongside each scan execution, when the override register is read before classification, and when each event writes to the activity log with the input version stamps that let the audit chain reproduce the classification. Programmes that store scan output in scanner UIs that overwrite per-cycle rows, in spreadsheets that lose the per-finding identifier across snapshots, or in ticketing tools that lack a recurring-detection identity cannot operate the change event surface coherently. The leverage point is consolidating findings into a workspace with structured per-finding identity and reading the diff against the structured records.

SecPortal exposes the structured records the diff reads through the workspace-scoped /api/scans/diff endpoint, the per-finding identity model in findings management, the override register through finding overrides, and the per-finding activity log. The platform does not currently ship packaged scheduled jobs that auto-classify coverage-dropped events at the cycle close; programmes that operate the change event discipline typically run the classification as a scheduled workspace job against the diff endpoint.

For the broader operating economics of cycle-to-cycle change, the vulnerability remediation throughput research covers how the new and resolved event rates combine to set the steady-state backlog. For the workflow side that consumes the change event stream into the cycle review cadence, the vulnerability backlog management use case covers the operating discipline the change event stream feeds.

Frequently Asked Questions

Operate change event generation against a record that keeps every cycle reproducible

SecPortal stores every scan execution against a workspace-scoped record and exposes /api/scans/diff for the per-finding new, fixed, and unchanged buckets against the composite module-plus-finding-id key, with module-level coverage gaps surfaced and override types annotated. The activity log captures every per-finding event so the change event stream reads alongside creation, assignment, status, override, and retest events on the same finding row. Continuous monitoring runs the cycle cadence the change event stream is produced on, and bulk import joins imported third-party output through the same per-finding identity discipline.