Vulnerability Management

Scan Coverage and the Wave Matrix: Knowing What You Missed

By PMAP Security Team 23 min read

Most vulnerability management programs measure themselves by what their scanners find. The harder question, and the one that decides whether your program is actually reducing risk, is what your scanners never looked at. A clean dashboard does not mean an asset is secure. It might just mean no tool ever scanned it, or that the one tool that did scan it has a blind spot for the technology running on that host.

This is the coverage problem. It sits underneath every coverage metric, every executive report, and every “we scan everything” claim. If you cannot say which scanner produced findings for a given asset, and when, then you cannot trust the absence of findings on that asset. You are reading silence as safety.

PMAP treats coverage as first-class data on the asset itself. On every asset detail page, three tabs answer the questions that a single scanner console cannot. The Coverage tab tells you which scanner integrations have actually produced findings for that asset. The Waves tab gives you a finding by scan cross-tab so you can watch a vulnerability open, close, and regress across successive scan cycles. The Timeline tab records the provenance of every asset metadata field, so you know which source wrote each value and whether a scanner ever silently changed it. Together they turn “we think we have coverage” into “here is exactly who scanned what, and here is what changed.”

This article explains why coverage data belongs on the asset, how to read the wave matrix as an operational signal rather than a static report, and how scanner enrichment keeps asset metadata current without ever overwriting the values your team deliberately curated. For the broader inventory and exposure picture, this piece sits under the attack surface pillar on attack surface and asset inventory. For the step-by-step procedure of opening these tabs and interpreting each cell, see the companion guide on reading the wave matrix and scan coverage.

The Blind Spot Problem: You Cannot Fix What No Scanner Sees

Vulnerability management has an asymmetry built into it. A finding is positive evidence. It says a scanner looked at this asset, recognized a condition, and reported it. The absence of a finding is not evidence of anything. It could mean the asset is clean. It could equally mean no scanner ran against it, or the scanner that ran does not understand the service on that port, or the scan was scoped to a subnet that excluded the host.

In a single-scanner world, you could at least reason about coverage by checking the scan target list. Modern programs do not live in a single-scanner world. A typical enterprise runs network scanners, web application scanners, authenticated agents, container and cloud posture tools, and the occasional manual import from Nmap or Masscan. Each tool has a different idea of the asset universe, a different cadence, and a different set of conditions it can detect. Stitching that together by hand, console by console, is exactly the work that does not get done when the team is busy.

The result is a silent gap. An asset shows zero findings, the dashboard counts it as healthy, and nobody asks the obvious follow-up question. Which scanner was responsible for that asset, and did it actually run? The blind spot is not a vulnerability you missed. It is a vulnerability you were never in a position to find, because no tool with the right capability ever looked.

PMAP closes this gap by deriving coverage from real evidence. It does not ask you to maintain a separate coverage spreadsheet. It reads the findings that already exist and tells you, per asset, which scanner integrations have produced at least one finding. The inversion is the useful part. An asset with an empty Coverage tab is not necessarily clean. It is a candidate for investigation, because nothing has demonstrably scanned it in a way that produced results.

Scan Coverage Per Asset

The Coverage tab on an asset detail page answers one precise question. Which scanner integrations have produced findings for this asset? It is backed by the GET /assets/{id}/scan-coverage endpoint, and the data is aggregated directly from the findings already imported into PMAP. There is no separate coverage tracking system to keep in sync, because coverage is simply a different view of finding data you already have.

The behavior that makes this trustworthy is also the behavior that surprises people the first time they see it. A scanner only appears in an asset’s coverage list if it has produced at least one finding for that asset. An integration that has run scans against the asset but produced zero findings does not appear. This is a deliberate design decision, and it matters for how you interpret the tab.

Reading it correctly takes a small shift in mindset. The Coverage tab is not a list of every scanner you have configured. It is a list of scanners that have demonstrably engaged with this specific asset and found something. If you expect a particular scanner to cover a host and it is missing from the list, that absence is the signal. Either the scanner never scanned the asset, or it scanned and found nothing. Both cases deserve a look, because a high-value host with no scanner producing findings is precisely the blind spot you set out to eliminate.

There is one constraint worth stating plainly so you do not misread the data. Coverage reflects findings that have already been imported into PMAP. A scanner that is integrated but has never had a scan imported will not appear in coverage, even if it has been running scans on the vendor side. The coverage view is honest about what PMAP can prove from ingested data, not about what might be happening in a scanner console PMAP has not received results from yet. That honesty is the point. Coverage you cannot back with imported evidence is coverage you should not count.

This is also where the per-asset framing earns its keep. Program-level coverage percentages hide the assets that matter. An organization can report ninety-five percent coverage and still have its three most critical crown-jewel systems sitting in the unscanned five percent. By attaching coverage to each asset, PMAP lets you answer the question at the granularity where decisions actually get made. Is this asset, the one that runs the payment service, covered by the scanners that can see its stack?

Reading the Wave Matrix

The Waves tab is where coverage stops being a snapshot and becomes a history. It is backed by GET /assets/{id}/wave-matrix and rendered as a cross-tab. Findings are the rows. Scan waves are the columns. Each cell shows the status of that finding during that scan wave. The structure is simple, and that simplicity is what makes it readable at a glance once you know what the cells mean.

Every cell carries one of four states, and each state is defined relative to a specific scan wave rather than the finding’s current status alone.

  • open means the finding was present and unresolved during that wave.
  • closed means the finding was resolved in that wave.
  • reopened means the finding re-appeared after a previous closure.
  • absent means the finding was not observed in that wave at all.

Read left to right along a single row, you get the life story of one vulnerability. You can see the wave where it first appeared as open, the wave where remediation landed and it went closed, and any later wave where it came back as reopened. Read top to bottom down a single column, you get the posture of the asset at one point in time. You see how many findings were open during that wave and how many had already been closed.

The absent state deserves attention because it is easy to misinterpret as good news. A cell reading absent does not assert that the finding was fixed. It asserts only that the finding was not observed in that particular wave. If a scan was scoped more narrowly that cycle, or a scanner did not run, a finding can read absent without anything having been remediated. The wave matrix does not pretend absent is closed. Keeping those two states distinct is exactly what lets you tell the difference between a vulnerability that was fixed and a vulnerability that simply fell out of scope.

One operational note keeps the tab usable on busy assets. The wave matrix is composed in-query from finding and scan data, so an asset with a very large finding history can produce a wide result set. Where the interface supports it, filter by date range or paginate so you are reading a focused slice of waves rather than the entire history at once. The goal is to look at the waves that bear on the decision in front of you, not to load every scan the asset has ever seen.

Spotting Regressions Across Waves

The single most valuable read on the wave matrix is the regression. A regression is a finding that transitions from closed back to open or reopened across waves. In plain terms, you fixed it, a later scan confirmed it was gone, and then a still later scan found it again. That pattern is a quiet failure mode that volume-based metrics never surface, because the finding count can look stable while the same vulnerability cycles in and out.

Regressions matter because they point at process problems, not just technical ones. A vulnerability that keeps coming back is rarely a one-off. It usually signals a configuration that drifts, a deployment pipeline that reintroduces an old package, a server rebuilt from a stale image, or a fix that was applied to a running host but never to the template behind it. The wave matrix makes this visible by laying the closure and reopening side by side in the same row. You do not have to reconstruct the sequence from scan logs. The row already tells the story.

PMAP also treats this as a program-level signal, not just a per-asset curiosity. The wave regression rate, the proportion of findings that transition from closed back to open or reopened across waves, is one of the coverage and enrichment metrics PMAP tracks. A rising regression rate is a clear message that remediations are not sticking, and it tells you to look upstream at the process that keeps undoing the fix rather than simply re-assigning the same finding to the same owner again.

How Scanner Enrichment Keeps Asset Metadata Current

Coverage and the wave matrix tell you what scanners found. Enrichment is the quieter mechanism that keeps the asset record itself accurate as scanners learn more about each host. When a scanner produces findings for an asset, it usually also reports observed facts about that asset, such as open ports, running services, detected technologies, installed software, operating system details, hostname, FQDN, and MAC address. PMAP’s enrichment merger takes that observed metadata and silently keeps the asset’s type_data current, without requiring an analyst to copy values by hand.

The set of fields the merger may touch is deliberately bounded. Only eight type_data field paths are on the enrichment allowlist: open ports, services, technologies, software, OS details, hostname, FQDN, and MAC. Any enrichment record that targets a path outside that allowlist is rejected at merge time. This is a guardrail, not a limitation. It means scanner-driven automation can keep the network-posture fields fresh while every other part of the asset record, the fields a human owns, stays out of reach of automated writes.

The array fields among those eight are merged by union rather than replacement. For open ports, services, technologies, and software, existing entries are preserved and newly observed entries are appended. One important consequence follows from this. The merger does not remove a value just because a scanner stopped reporting it. If a port shows up once and then disappears from a later scan, enrichment will not silently drop it from the asset. That conservatism is intentional, because a scanner not reporting a value is not the same as that value being gone, and treating the two as identical is how automated systems quietly corrupt an inventory.

Two denormalized columns ride along automatically. The os_name and os_version fields on the asset record are synced from type_data.os_details by a database trigger, and they are read-only from the API. You cannot set them directly, and you do not need to. They always reflect the latest enriched OS value, which keeps faceted search and OS-family filtering accurate without anyone maintaining a parallel copy. This is the small, invisible kind of automation that pays off across thousands of assets, because the alternative is a thousand stale OS strings nobody remembers to update.

Source Precedence So Manual Curation Wins

The obvious risk with silent automated writes is that a scanner overwrites something a human got right on purpose. PMAP prevents this with a source-precedence ladder that every enrichment write must respect. The order, from highest authority to lowest, is manual > rule > runbook > scanner > import. A scanner enrichment record never overwrites a field whose current value came from a higher-ranked source. If the hostname on an asset was set manually, a scanner observing a different hostname does not get to clobber it.

This ladder is the contract that makes automation safe to trust. Manual curation is the most authoritative source for a reason. When a security engineer sets a field by hand, they usually know something the scanner does not, such as the canonical name a host should carry in the inventory regardless of what reverse DNS happens to say this week. Rules and runbooks sit above scanners because they represent deliberate organizational policy. Scanners sit above raw imports because a live scan is generally fresher and more trustworthy than a one-time file load.

The practical effect is that you get the best of both behaviors at once. The fields nobody has touched stay continuously fresh from scanner observations, so your inventory keeps pace with reality. The fields your team curated deliberately stay exactly as they were set, so the system never silently undoes a decision a human made on purpose. Automation fills the gaps without overwriting the judgment.

Field-Level Locking and Conflict Review

Source precedence handles the common case where a field already has a higher-authority value. Field-level locking handles the case where you want an explicit, durable guarantee that nothing automated will ever touch a specific field again. An administrator can lock an individual type_data field, and once locked, that field is sealed against silent enrichment writes.

The behavior when a scanner tries to write to a locked field is the part worth understanding, because it is more useful than a plain rejection. When an incoming scanner value targets a locked field, PMAP does not write it and does not throw it away. It stores the incoming value as conflict_pending. No write occurs to type_data until an administrator resolves the conflict or unlocks the field. The scanner’s observation is captured, the curated value is protected, and the discrepancy is queued for a human to look at rather than discarded.

This matters because a scanner reporting a different value is information, even when you do not want it applied automatically. Maybe the scanner is right and the locked value is stale. Maybe the locked value is correct and the scanner is confused by a NAT or a load balancer. Either way, you want to know that the two disagree. By recording the conflict instead of silently applying or silently dropping it, PMAP turns a potential data-quality incident into a reviewable item. Conflicts surface in the Timeline tab, and an administrator resolves each one deliberately, either by overriding the field with the new value or by keeping the curated value and leaving the lock in place.

The design principle running through all of this is the absence of silent overwrites. At no point does a scanner quietly replace a value a human chose to protect. Every such attempt is either skipped because precedence forbids it or held as a conflict for review. That predictability is what lets a team turn on automated enrichment without worrying that it will erode the inventory they worked to clean up.

The Enrichment Audit Trail

Behind every enrichment decision is a per-field audit log, and it is the record that makes the whole mechanism accountable. Every enrichment attempt is written with one of five outcomes, and reading those outcomes tells you exactly what happened to each field and why.

  • applied means the value was written to type_data.
  • skipped_locked means the field was locked or out-ranked, so the value was not written.
  • conflict_pending means a conflict was detected and queued for review.
  • user_override means an administrator resolved a conflict by overriding the field.
  • no_op means the incoming value was identical to the current value, so nothing changed.

This vocabulary is precise on purpose. The difference between applied and no_op tells you whether an enrichment run actually changed anything or simply confirmed what was already there. The difference between skipped_locked and conflict_pending tells you whether the system declined the write by policy or paused it for a human. When an auditor asks how a particular OS value got onto an asset, the answer is in the log, with the source that wrote it, the outcome, and the timestamp.

The audit history lives on the Timeline tab of the asset, and access to it is deliberately restricted. The GET /api/v1/asset-enrichment/{id}/enrichment-history endpoint is available only to platform administrators or sufficiently privileged company-scoped users, and the Timeline tab does not show for other roles. Provenance data is sensitive, because it reveals how an asset’s metadata was assembled, and PMAP treats it accordingly. The same multi-tenant scope filter that governs every other asset read applies to the audit history, so no one sees provenance for assets outside their tenant.

There is one retention nuance that matters for compliance. PMAP runs a background scheduler that periodically purges stale provenance rows, the working records the merger uses to decide precedence. The compliance audit log itself is retained and is not purged by that scheduler. The distinction is deliberate. The operational provenance state can be trimmed to keep the system lean, while the audit trail that an assessor would want to inspect stays intact.

Turning Coverage Data Into a Scanning Strategy

Coverage, the wave matrix, and enrichment are not just diagnostic tabs to open when something looks wrong. Read together over time, they form the feedback loop that tells you where to point your scanning effort next. The data answers strategy questions that a raw finding count cannot.

Start with reach. Two enrichment metrics describe how far your scanning program actually extends across the inventory. The proportion of assets with enriched OS data tells you how many assets your scanners have learned enough about to populate type_data.os_details. The proportion of assets with at least one scanner in the Coverage tab tells you enrichment reach, the share of your inventory that has any demonstrated scanner engagement at all. Assets missing from both populations are your real blind spots, the hosts no tool has meaningfully touched.

Then look at the enrichment outcome distribution. The mix of applied, skipped_locked, conflict_pending, and no_op outcomes is a read on the health of your automation. A healthy program shows enrichment doing useful work with a manageable conflict backlog. A growing conflict_pending count is a queue forming, a sign that scanners and curated values are diverging on more fields than your team is resolving, and it points you at a review backlog before it becomes a data-quality drift.

Finally, treat the wave regression rate as a leading indicator for remediation durability. Findings that transition from closed back to open or reopened across waves are the fixes that did not hold. A coverage-driven strategy uses these three signals together. Coverage tells you where you are not looking. The conflict backlog tells you where your inventory truth is at risk. The regression rate tells you where your remediations are not sticking. Each one redirects effort to a place a flat finding count would have left invisible.

How PMAP Makes Coverage Visible

The thread connecting every part of this article is a single conviction. Coverage is data you should be able to see, not a claim you have to take on faith. PMAP makes it visible by attaching it to the asset, where the decisions actually happen, and by deriving it from evidence that already exists rather than from a separate system you would have to maintain.

The Coverage tab exposes which scanner integrations have demonstrably produced findings for an asset, so an empty list becomes an investigation rather than a comfortable silence. The wave matrix turns scan history into a readable cross-tab where regressions reveal themselves in a single row. Scanner enrichment keeps the asset record current within a bounded allowlist, governed by a precedence ladder that lets manual curation win and by field locking that holds conflicts for review instead of overwriting anyone’s work. The enrichment audit trail records every decision with a precise outcome, restricted to the people allowed to see provenance, and retained for compliance even as working state is purged.

None of this requires analysts to cross-reference five scanner consoles. The blind spots, the regressions, and the metadata conflicts surface where the work is done, on the asset itself. That is what it means to know what you missed. Not to hope you caught everything, but to be able to point at the gap and decide what to do about it.

If you want the procedural walkthrough of opening these tabs and interpreting each cell on a live asset, read the guide on reading the wave matrix and scan coverage. To build the clean inventory that coverage data sits on top of, see the related article on maintaining a trustworthy asset inventory, and to make scope reusable across scans, see the piece on static and dynamic asset groups. For the bigger picture of how inventory and exposure fit together, the attack surface and asset inventory pillar frames where coverage belongs in a vulnerability management program.

For context on what comprehensive testing coverage means as a discipline, NIST SP 800-115 sets out technical security testing and assessment expectations, and CIS Critical Security Control 7 frames continuous vulnerability management as an ongoing program rather than a one-time scan. The CISA Known Exploited Vulnerabilities catalog is a useful reminder of why regression tracking matters, because a vulnerability that reopens may well be one attackers are actively exploiting.

> See it on your own inventory. Read the asset inventory datasheet and use PMAP coverage views to find your scanning blind spots.

Frequently Asked Questions

What does the wave matrix show?

The wave matrix is a per-asset cross-tab of findings against scan waves, backed by GET /assets/{id}/wave-matrix. Findings are the rows and scan waves are the columns. Each cell shows the finding’s status during that wave, using one of four states: open (present and unresolved), closed (resolved in that wave), reopened (re-appeared after a previous closure), or absent (not observed in that wave). Reading a row left to right shows the full lifecycle of one vulnerability across scan cycles, which is how you spot a finding that was fixed and later came back.

Why does a scanner not appear in an asset’s coverage list?

The Coverage tab lists only scanner integrations that have produced at least one finding for that asset. An integration that ran a scan against the asset but produced zero findings does not appear. Coverage is also derived from findings already imported into PMAP, so a scanner that is integrated but has never had a scan imported will not appear even if it has run scans on the vendor side. An empty or unexpectedly short coverage list is a signal to investigate, not a confirmation that the asset is clean.

Can scanner enrichment overwrite a manually set asset field?

No. Enrichment follows a source-precedence ladder of manual > rule > runbook > scanner > import, and a scanner record never overwrites a field whose current value came from a higher-ranked source such as manual curation. On top of that, an administrator can explicitly lock a field. When a scanner tries to write to a locked field, the incoming value is stored as conflict_pending for review and type_data is not changed. There are no silent overwrites of curated values.

How do I detect a vulnerability that regressed across scans?

Open the asset’s Waves tab and read across the finding’s row. A regression appears as a cell that transitions from closed back to open or reopened in a later wave, which means the finding was fixed, confirmed gone, and then found again. At the program level, PMAP tracks a wave regression rate, the proportion of findings that move from closed back to open or reopened across waves, so you can see whether remediations are sticking across the whole inventory rather than checking one asset at a time.

Which asset fields can scanner enrichment update?

Enrichment may write to only eight type_data field paths: open ports, services, technologies, software, OS details, hostname, FQDN, and MAC. Any enrichment record targeting a path outside this allowlist is rejected at merge time. Array fields such as open ports and services are merged by union, so existing entries are preserved and new ones appended, and the merger does not remove a value just because a scanner stopped reporting it. The os_name and os_version columns are synced automatically from OS details by a database trigger and are read-only from the API.

Who can see the enrichment audit history?

The enrichment audit history is admin-only. The GET /api/v1/asset-enrichment/{id}/enrichment-history endpoint is restricted to platform administrators or sufficiently privileged company-scoped users, and the Timeline tab that displays it does not show for other roles. The same multi-tenant scope filter that governs all asset reads applies here, so provenance for assets outside your tenant is never exposed. Each entry records the source, the outcome (applied, skipped_locked, conflict_pending, user_override, or no_op), and a timestamp.

What is the difference between an absent and a closed cell in the wave matrix?

A closed cell means the finding was actively resolved in that wave. An absent cell means only that the finding was not observed in that wave, which can happen if a scan was scoped more narrowly that cycle or a scanner did not run. PMAP keeps the two states distinct on purpose, because reading absent as if it were closed would let a vulnerability that simply fell out of scope look like a remediation that never happened.

author avatar
PMAP Security Team

Newsletter

Get the next writeup in your inbox

One short email when a new case writeup or detection deep dive ships. No marketing drip, no third-party tracking.