Most enterprise security programs do not have a scanner problem. They have a scanner *math* problem. Run a network vulnerability scanner, a web application scanner, a static analysis tool and a software composition scanner against the same estate, and you do not get four neat views of risk. You get four separate inboxes, each rating the same weakness differently, each numbering it differently, and each demanding its own triage pass. The same TLS misconfiguration shows up in two tools. The same vulnerable dependency appears in three. Analysts end up triaging one real issue four times, and the consolidated risk picture lives in a spreadsheet that goes stale the moment the next scan finishes.
Multi-vendor scan import is the layer that fixes the math. Instead of treating each scanner as an island, PMAP ingests results from every connected tool, normalizes them, and runs every inbound result through a correlation engine that decides whether it is genuinely new or a restatement of something already in the queue. The output is one deduplicated finding set that holds steady regardless of how many scanners feed it. This article explains how that import path works, why it is built the way it is, and what behavior to expect when you point a real multi-vendor stack at it. For the broader orchestration picture, see the full multi-vendor scan orchestration model.
Why Every Scanner Becomes Its Own Silo
The silo problem is structural, not accidental. Each scanner is designed to be authoritative inside its own domain. A network scanner owns plugin IDs and host references. A DAST tool owns URLs, parameters and HTTP request and response pairs. A SAST engine owns file paths, line numbers and taint flows. None of them was built to recognize that a finding it just produced overlaps with a finding produced by a competitor’s product. They cannot, because they never see each other’s output.
Enterprise environments make this acute. It is common to run three to ten scanners concurrently across infrastructure, web, code and dependencies. Without a unifying layer, three consequences follow in order. First, duplicates multiply, because the same weakness on the same asset is reported independently by every tool that can see it. Second, severity drifts, because each vendor rates the same issue on its own scale and nothing reconciles them. Third, triage cost compounds, because an analyst pays the full cost of reviewing each duplicate as if it were a distinct problem.
The cost is not theoretical. If four scanners each surface 2,000 findings and a third of those overlap, you are not looking at 8,000 issues. You are looking at far fewer real issues buried inside thousands of restatements. The job of import is to collapse the restatements before a human ever sees them, so that the queue reflects reality rather than tool count.
The Supported Vendor Catalog by Category
PMAP’s API-based import path covers a deliberately broad vendor catalog, organized by the kind of testing each tool performs. The breadth matters because the value of correlation grows with the number of overlapping sources. Two scanners produce some duplicates. A full multi-discipline stack produces many, and that is exactly where a single correlated queue earns its place.
| Category | Supported vendors | |—|—| | VM and infrastructure | Nessus, Tenable SC, Tenable IO, Qualys VMDR, Rapid7 InsightVM, Nuclei | | DAST | Acunetix, Invicti, Burp Suite Enterprise | | SAST | SonarQube, Checkmarx SAST, Checkmarx One, Fortify SAST | | SCA and supply chain | Snyk Open Source, Black Duck SCA, Sonatype Lifecycle | | Container | Prisma Cloud | | Mobile | MobSF |
On top of the API-connected vendors above, PMAP accepts file-based imports for offline or air-gapped scans. NessusXML, SARIF 2.1, Nmap XML, Masscan JSON or list output, and Nuclei JSONL can all be uploaded directly. That covers the case where a scan ran somewhere the platform cannot reach the vendor API, and it means a disconnected environment is not a dead end for consolidation.
The categorization is not cosmetic. Each connector produces a normalized finding that carries the source-specific fields its discipline needs. A SAST result arrives with file path, line numbers, code snippet and taint flow. An SCA result arrives with component name, version, ecosystem, dependency path and license. A DAST result arrives with the HTTP request and response and the affected parameter. Correlation operates on top of that normalized shape, which is what lets results from very different tools land in the same finding when they describe the same weakness.
The 4-Case Correlation Pipeline at Ingest
Every result that enters PMAP from any scanner passes through the same decision engine before it becomes a finding. That engine answers one question for each inbound result: does this vulnerability already exist in the platform, or is it new? It answers with a four-case pipeline, and understanding those four cases is the key to understanding why the deduplicated queue behaves the way it does.
The pipeline runs in a fixed order:
- CASE 1, scanner reference match. The engine first looks up an existing finding by the scanner’s own unique key, for example a Nessus plugin and host combination. If that key already maps to a finding, the engine updates that finding’s fields in place rather than creating a new row. This is the fast path for re-ingesting the same scan from the same tool.
- CASE 2, fingerprint match. If there is no scanner-reference match, the engine looks up an existing finding by SHA-1 fingerprint within the same company. The fingerprint is scanner-agnostic, which is what enables cross-scanner deduplication. A weakness first reported by one tool and later by another resolves to the same finding here.
- CASE 3, closed finding reopen. If a match is found through either lookup and that finding is currently closed, the engine does not silently update a dead record. It reopens the finding, preserves its history, and re-engages the rule engine. Recurrence is treated as a real event, not a no-op.
- CASE 4, new finding create. Only when no existing finding matches does the engine create a new, fully populated finding, complete with the source-specific SAST, DAST and SCA fields the result carried.
Two design choices in this pipeline deserve emphasis. The scanner-reference lookup takes absolute priority over the fingerprint lookup, which keeps repeated runs of the same tool idempotent and cheap. And rule evaluation fires only on ActionCreated and ActionReopened, not on plain updates, so the rule engine reacts to genuinely new or recurring risk rather than re-firing on every routine re-scan. The correlation engine itself is a focused internal component with a single job. If you want the standalone mechanics of that engine, the correlation and deduplication engine deep dive covers it in isolation. Here the focus is what correlation does *at import time*.
Cross-Scanner Fingerprints That Survive Re-scans
The fingerprint is the mechanism that makes cross-scanner deduplication possible, so it is worth being precise about how it is built. The V1 fingerprint is a SHA-1 hash of a normalized title, the asset identifier, and a normalized endpoint, with an optional template identifier appended when one is present.
Normalization is what gives the fingerprint stability. The title is lowercased and trimmed, so capitalization and stray whitespace do not produce false differences. The endpoint is stripped of its scheme, so https://, http:// and ftp:// prefixes do not matter, and everything after the first path separator is removed. A port is appended only when it is supplied separately and is meaningful. The result is a fingerprint that stays the same across re-scans of the same vulnerability on the same asset, and critically, the same across *different scanners* reporting that vulnerability, because each connector feeds normalized inputs into the same hash.
This is the difference between correlation and naive string matching. A naive approach that compared raw scanner titles would treat SSL/TLS weak cipher and Weak TLS cipher suite supported as two different problems. Fingerprinting on normalized, structured inputs collapses them when they describe the same weakness on the same asset, and keeps them apart when they genuinely differ. For a side-by-side of why this beats simple deduplication, see correlation versus naive dedup.
Closed Finding Reopen, Not Silent Drop
One of the most consequential behaviors in the import path is what happens when a scanner re-reports something a team has already closed. The naive answer is to drop it, on the assumption that a closed finding is settled business. That answer is wrong, and PMAP is built to reject it.
When an inbound result matches a finding whose status is closed, the correlation engine produces an ActionReopened outcome. The finding’s status returns to open, its reopen_count is incremented so the recurrence is countable, and rule evaluation is triggered so any severity or routing logic applies to the reopened finding immediately. The fingerprint lookup is deliberately built to support this. It matches findings in *any* status, including closed, precisely so the reopen path can fire. An open finding always wins over a closed one when both exist, but a closed match is never ignored.
This matters because recurrence is a signal, not noise. A vulnerability that was fixed and has come back tells you something specific. A control regressed, a deployment reverted a patch, or the remediation never actually held. If import silently dropped re-reported closed findings, that signal would vanish and the team would believe a problem was solved when it was not. By reopening rather than dropping, PMAP preserves both the history of the original work and the visibility of the regression, and the reopen_count becomes a durable metric for how often fixes fail to stick.
Severity Governance: Vendor Severity Is Never Authoritative
A subtle but important principle runs through the entire import path. PMAP never persists a vendor’s severity rating as authoritative. Each connector produces a normalized severity through its own mapper, and that normalized value is what enters the platform. The original vendor severity is preserved for audit, but it does not get to dictate the risk picture.
The reason is consistency. If four scanners each rate the same issue on their own scale, and the platform simply trusted whichever scanner reported it last, the severity of a finding could change every time a different tool ran. That would make prioritization meaningless. By routing every result through a normalization mapper and keeping the original severity only as a reference, PMAP ensures the risk picture stays consistent no matter which tool surfaced the finding.
Severity governance does not stop at normalization. Two further controls apply on import. An import_severity_threshold discards results below a configured minimum before they are ever persisted, so low-signal informational noise never enters the queue. And the rule engine can override severity after correlation, applying organization-specific logic on top of the normalized baseline. The original severity is always retained, so an auditor can always see exactly what each vendor claimed and exactly what PMAP decided.
Import Filters: Plugin Blocklist and Severity Threshold
Not every scanner result deserves a place in the finding queue, and import gives operators two filters to enforce that judgment before correlation runs. Both are applied inside the vendor-specific importer, ahead of the correlation engine, which means filtered-out results never consume dedup work and never reach the queue at all.
The first filter is a plugin-ID blocklist, configured as exclude_plugins. When specific plugin IDs are known to produce false positives in a given environment, listing them suppresses those signatures at ingest. This is the right place to handle a noisy check that a team has investigated and decided is not actionable for their estate. The suppression happens once, at the import boundary, rather than forcing analysts to dismiss the same false positive on every scan.
The second filter is the minimum severity threshold, severity_filter. When an import is run with a threshold, results below it are discarded before correlation. A team that does not want informational and low findings polluting an already large queue can set the floor and keep the import focused on what they intend to act on. Both filters are deliberately positioned before correlation so they reduce work rather than merely hiding results after the fact.
Multi-Tenant Import Routing
In a managed-service or multi-subsidiary context, a single platform-level scan may need to feed findings into a specific company and project. Import supports this without forcing operators to fork or modify the underlying scan record. The import request accepts company_id and project_id overrides, and those overrides scope every created finding to the chosen subsidiary and project.
The scan record itself is not changed. This separation matters operationally. The scan remains a single source of truth about what ran, while the findings it produced are routed to the correct tenant boundary at import time. A platform administrator can run one scan and direct its output precisely, and every list query downstream still enforces tenant scope, so out-of-tenant data never leaks across the boundary. Out-of-tenant scan probes return a 404 rather than a 403, so a curious user cannot even confirm the existence of a scan they are not entitled to see.
Idempotency and Retry Safety
Imports fail mid-flight in the real world. A network blip, a vendor API timeout or a restarted worker can interrupt a run partway through. The import path is built so that this is a non-event, because re-importing the same vendor scan produces no duplicates.
The guarantee rests on two mechanisms working together. Connector HTTP calls use upsert semantics, so re-fetching the same external records updates existing rows rather than inserting new ones. And the correlation pipeline’s scanner-reference lookup means that re-running an import hits the same external IDs and resolves them to the findings they already created, taking the update path rather than the create path. The practical consequence is that an interrupted import can simply be re-run. There is no cleanup step, no risk of doubling the queue, and no need to reason about which records made it through before the failure.
The counters reflect this discipline. The findings_imported counter is incremented only by the count of newly created findings. Re-runs that produce updates or reopens do not inflate it. That keeps the metric honest. It measures genuinely new findings introduced by a wave, not the total volume of results processed, so an operator reading it gets a true picture of what changed rather than a number that grows every time an import is retried.
File-Based Import for Offline Scans
Not every scan runs somewhere PMAP can reach the vendor API. A scan executed inside an isolated segment, a one-off scan from a tool that is not yet connected, or a result exported from a customer environment all need a path in. File-based import is that path.
The platform accepts NessusXML for native Nessus exports, SARIF 2.1 for the broad ecosystem of static analysis and code scanning tools that emit that standard format, Nmap XML and Masscan output for network discovery, and Nuclei JSONL for template-based scanning. An uploaded file is parsed, and its findings and assets are created or enriched idempotently, exactly as an API-driven import would be. The file flows through the same correlation pipeline, which means an uploaded SARIF result deduplicates against API-imported results just as cleanly as if it had arrived over a live connection.
This closes a gap that often forces teams back into spreadsheets. An air-gapped scan is no longer a special case that lives outside the consolidated queue. It enters the same finding set, gets the same correlation treatment, and contributes to the same risk picture as everything else. The SARIF support in particular is worth noting, because it means any tool that emits the OASIS SARIF 2.1 standard can feed PMAP without a bespoke connector.
Reading the Findings Delta After Each Wave
Importing results is only half the value. The other half is understanding what each wave actually changed. After an import completes, the findings delta widget answers that directly, breaking the wave down into new versus regression versus total, sliced by severity.
The three categories map to the three things an operator cares about after a scan. *New* findings are issues this wave surfaced for the first time. *Regression* findings are the reopens, the issues that were closed and came back, which deserve attention because they represent failed fixes. *Total* is the full picture by severity, the post-import state of the queue. Reading this delta after every wave turns a scan from an opaque batch operation into a clear before-and-after statement of how the risk posture moved.
This is also where the discipline of the import counters pays off for the human reading the screen. Because the engine distinguishes created, updated and reopened actions, the delta can present an honest accounting rather than a raw dump of every result processed. An analyst sees that a wave introduced a specific number of genuinely new critical findings and reopened a specific number of previously closed ones, and can decide where to spend attention accordingly.
How PMAP Collapses Scanner Sprawl Into One Queue
Step back from the mechanics and the shape of the value is simple. A team running a multi-vendor stack should triage each real issue once, see a severity that does not flip depending on which tool ran last, and never lose track of a vulnerability that came back from the dead. Multi-vendor scan import delivers all three because every result, from every supported source, flows through the same normalization and the same four-case correlation pipeline before it becomes a finding.
That is what separates consolidation from a shared inbox. A shared inbox just piles every tool’s output into one list and leaves the deduplication to humans. PMAP does the deduplication at ingest, governs severity centrally, reopens recurrences instead of dropping them, and keeps the whole operation idempotent so retries are safe. The scanner sprawl that produces four silos becomes one correlated queue, and the queue reflects the number of real issues rather than the number of tools you happen to run.
If you want to see the import boundary in detail from a single-vendor angle, you can import a Tenable Nessus scan step by step in the practitioner guide. That walkthrough shows the exact import controls in action. Two adjacent capabilities complete the picture. Scan lifecycle management covers how scans are run, monitored and controlled across vendors, and scan scheduling and live sync covers how those imports stay current automatically. For where multi-vendor import sits in a broader program, the CIS Controls v8 Control 7 on continuous vulnerability management is a useful external frame.
See how PMAP turns many scanners into one correlated, deduplicated finding set.
Frequently Asked Questions
How does PMAP deduplicate findings across different scanners?
Every inbound result passes through a four-case correlation pipeline. The engine first tries to match an existing finding by the scanner’s own reference key, then by a scanner-agnostic SHA-1 fingerprint built from a normalized title, asset and endpoint. Because the fingerprint is computed from normalized inputs rather than raw scanner text, the same vulnerability on the same asset resolves to one finding even when different scanners report it. A match updates the existing finding instead of creating a duplicate.
What scanners does PMAP support for import?
The API-based import path covers VM and infrastructure scanners including Nessus, Tenable SC, Tenable IO, Qualys VMDR, Rapid7 InsightVM and Nuclei, DAST tools including Acunetix, Invicti and Burp Suite Enterprise, SAST tools including SonarQube, Checkmarx SAST, Checkmarx One and Fortify SAST, SCA tools including Snyk Open Source, Black Duck SCA and Sonatype Lifecycle, plus Prisma Cloud for containers and MobSF for mobile. File-based import additionally accepts NessusXML, SARIF 2.1, Nmap XML, Masscan and Nuclei JSONL uploads.
What happens when a scanner re-reports a finding I already closed?
The finding is reopened, not dropped. When an inbound result matches a closed finding, the correlation engine reopens it, increments its reopen count and triggers rule evaluation. The fingerprint lookup matches findings in any status precisely so this reopen path can fire. This preserves the history of the original work while making the recurrence visible, and the reopen count becomes a durable measure of how often fixes fail to hold.
Does PMAP trust the severity rating from each scanner?
No. Vendor severity is never persisted as authoritative. Each connector normalizes severity through its own mapper, and that normalized value is what enters the platform, while the original vendor severity is preserved only for audit. An import severity threshold can discard results below a configured minimum before they are persisted, and the rule engine can override severity after correlation. This keeps the risk picture consistent regardless of which tool reported a finding.
Can I import a scan from a tool PMAP cannot reach over the network?
Yes, through file-based import. You can upload NessusXML, SARIF 2.1, Nmap XML, Masscan output or Nuclei JSONL directly. The uploaded file is parsed and its findings flow through the same correlation pipeline as an API-driven import, so an offline scan deduplicates against your existing finding set exactly as a live import would. This means air-gapped and disconnected scans still contribute to the same consolidated queue.
Is it safe to re-run an import that failed partway through?
Yes. Re-importing the same vendor scan produces no duplicates. Connector calls use upsert semantics and the correlation engine’s scanner-reference lookup resolves repeated external IDs to the findings they already created, so a re-run takes the update path rather than creating new rows. The findings imported counter is incremented only by newly created findings, so retries do not inflate it. An interrupted import can simply be run again with no cleanup step.
How do I tell what changed after an import?
Use the findings delta. After an import completes, the delta widget breaks the wave into new versus regression versus total findings, sliced by severity. New findings are issues surfaced for the first time, regression findings are reopened closed findings, and total is the post-import state of the queue. Because the engine distinguishes created, updated and reopened actions, the delta gives an honest accounting of how the wave moved your risk posture rather than a raw count of every result processed.