The arithmetic
Three things multiply our finding count: how many assets we run, how many scanners we point at them, how often those scanners fire. Our triage capacity grows when we hire someone.
Trivy scans every image we build. Nessus checks every host we run on a schedule. Static and dynamic application scanners cover our code as well, though those findings go to the development teams, who triage them where the code lives. Penetration testers file their results into the same system as everything else. None of it slows down while we catch up.
The real cost hides inside the backlog. Forty thousand open findings will bury the four that an attacker uses this quarter, and no dashboard shows you that happening.
The free context is thinning out
NIST said in April that its own capacity has run out. It enriched nearly 42,000 CVEs in 2025, 45% more than in any prior year, and called that not enough to keep pace. Since 15 April 2026 it enriches three categories first: entries in CISA’s Known Exploited Vulnerabilities catalogue2, software used within the federal government, and critical software under Executive Order 140283. Everything else publishes as lowest priority, and NIST no longer routinely adds its own severity score when the reporting authority already supplied one.1
Two things follow for anyone triaging on CVSS. More CVEs will reach us with no NVD score and no affected product list, so that work lands on our team. And the one category NIST still enriches within a business day is KEV, which says something about which signal it trusts.
Why teams reach for AI here
The impulse makes sense. Triage looks like judgment work, so a machine that imitates judgment looks like the fix.
One finding costs us about ten minutes of lookup: opening the scanner record, checking whether the CVSS score holds up and clears the bar for attention, checking for a vendor patch, working out whether the host runs the affected component in a configuration that exposes it. Four systems, four answers.
The decision that follows takes seconds, and it runs on a rule that fits on an index card. Buying intelligence solves the wrong half of that problem.
Determinism buys us things a model cannot. We can show an auditor the rule itself. We can replay last year’s findings through a rule set and see what it would have said before we ship it. When a rule misfires, we find the line and change it.
There is a security argument too. CVE descriptions and vendor advisories carry text that an attacker can influence. We would rather not feed that text to something that takes actions on our infrastructure.
What we built first
Trivy covers our container images and our infrastructure as code. Nessus covers hosts and network. A script pushes both sets of results into DefectDojo, and our penetration test findings land in the same place. DefectDojo handles deduplication and holds our review state: risk accepted, false positive, verified.
A second script reads DefectDojo through filters, scores what comes back on CVSS, checks tags such as internet-facing and public-audience, and raises an alert on the highest scoring findings so someone looks at them that day.
That bought us a single queue, one system of record, and an alert path that fires on the obvious emergencies. It catches what we built it to catch.
It also left most of our triage where it started, with an analyst working through DefectDojo by hand. For a while we assumed we needed better scoring. CVSS ranks how bad a vulnerability could be for a hypothetical organisation with a hypothetical deployment. It says nothing about whether anyone exploits the thing, or whether the affected host answers the public internet, so exploitability data looked like the missing piece.
The half we missed
Both of our scripts move findings in the same direction. One pushes them into DefectDojo. The other pushes a subset toward a human. Nothing we had built took a finding away from a human.
So the queue kept growing, and an analyst still opened each item to decide it was not worth opening. That was the work to kill first.
One rule that removes findings already runs in our setup, and we never counted it as automation. DefectDojo closes a finding when the next scan stops reporting it, so a decommissioned host takes its vulnerabilities with it and no analyst reviews them. That is the pattern we needed more of, and we had never written a second rule like it.
Two more drain most of what remains, and neither one needs intelligence:
No fix exists. The vendor has not shipped a patch. Nobody can act on it today, so it belongs on a watch list with a recheck date, out of the review queue.
Nothing can reach it and nobody exploits it. Internal host, absent from CISA’s catalogue of known exploited vulnerabilities, low score on the exploit prediction system. It goes into the monthly patch cycle and stops appearing in anyone’s review.
One more change pays for itself. We triaged findings, when the unit of work is the fix. A single base image update closes hundreds of Trivy findings across dozens of services. A single service version upgrade closes the same Nessus finding on every host running it. Group by remediation action and the queue collapses before anyone reads a line of it.
What we are building now
Four inputs, all of which we can fetch or already hold:
- Exploitation: CISA KEV listing, EPSS probability. Both are free, both key on CVE, both cost an afternoon of engineering time.
- Exposure: our existing tags, which carry network reachability and audience size as separate signals.
- Fix availability: Trivy and Nessus both report it.
- Asset criticality: our inventory, rated low, medium or high.
Six decisions, each with a clock. The shape borrows from SSVC, the decision tree approach CISA publishes, with our own thresholds in it. Rows evaluate top down and the first match wins:
| Exploitation | Exposure | Fix available | Decision | Clock |
|---|---|---|---|---|
| In CISA KEV | Internet-facing, public audience | Yes | Fix now | 24 hours |
| In CISA KEV | Internet-facing | No | Compensating control | 24 hours |
| In CISA KEV | Internet-facing, limited audience | Yes | Fix this week | 7 day |
| EPSS above 0.1 | Internet-facing | Yes | Fix this week | 7 days |
| In CISA KEV | Internal only | Yes | Fix in two weeks | 14 days |
| No KEV entry, low EPSS | Internal only | Yes | Next patch cycle | 30 days |
| Any | Any | No | Watch list | Recheck in 30 days |
A compensating control changes the environment instead of the software: a proxy or firewall rule that blocks the affected path, a feature switched off, a service taken off the internet. The finding stays open with the control recorded against it, and the clock restarts when a patch ships.
High criticality moves a finding one row up the table. Medium and low leave it where the table puts it, and nothing moves a finding down. A KEV listed flaw on our customer file storage gets the 7 day clock rather than 14.
This is our starting point. The thresholds, the clocks and the criticality rule are ours, and we expect the shadow run to tell us which of them we got wrong.
We route penetration test findings past the table. The tester already did the triage by hand, walked the attack path, and scored the finding with a full CVSS vector including the exploitability metrics. Some of those findings carry a CVE and some do not, so KEV and EPSS have nothing to key on. They go to the report owner with the tester’s severity and the remediation date agreed in the debrief.
The table runs in shadow mode against last quarter’s findings while we compare its calls against what our analysts decided by hand. Three cases from that replay:
A CVSS 9.8 in a container library, no KEV entry, EPSS below 0.01, running on an internal build agent. Our current filter posts a Slack message to the team. The table sends it to the monthly cycle and nobody reads it.
A CVSS 6.5 on an internet-facing host serving a public audience, listed in KEV, patch available. Our current filter drops it below the alert threshold. The table makes it a 24 hour item.
A CVSS 8.1 on an internet-facing host, listed in KEV, with no vendor patch. Today it returns to the review queue every cycle and someone re-reads it without being able to act. The table gives it 24 hours for a compensating control, so we block the affected path at the proxy and record that against the finding until a patch exists.
Our old filter mishandles all three, in three different directions.
What it costs and how we measure it
The budget goes somewhere unglamorous. Tag coverage decays the moment someone launches a service without tagging it, so tag coverage becomes a number we track rather than a thing we assume. Scan coverage needs an owner, because DefectDojo closes findings that stop appearing in scans, and a host that drops out of Nessus scope through a broken agent or a missed network segment looks exactly like a host we patched. Risk acceptances in DefectDojo need expiry dates, because a permanent acceptance is a decision nobody revisits after the person who made it leaves.
Four numbers tell us whether this works:
- Share of findings the pipeline decides without a human
- Human touches per finding
- Median time from ingest to decision
- Findings we auto-deferred that later turned up in KEV
That last one keeps us honest. A pipeline that never surfaces a miss is a pipeline nobody checks.
Three things this will not do.
- Rules rot, so someone owns them and reviews them each quarter, the same way someone owns a firewall rule set.
- Our four inputs say nothing about whether a host uses the affected component in an exploitable configuration. Trivy reports that the package sits in the image. Whether the service loads it, whether the vulnerable feature is switched on, whether anything reaches it in that deployment: someone still has to look.
- And the human queue never reaches zero. We want it down to the few percent of findings that are ambiguous, handled by someone with time to think about them instead of a morning spent rescoring CVSS by hand.
If your queue looks like ours did
Our stack is a common one: two scanners, DefectDojo, a couple of scripts, and a review process that quietly turned into a full time job. If yours resembles it, the diagnosis probably transfers, and the expensive part sits in tag coverage, scan coverage, and the decision about which findings you will let a rule close without a human reading them.
Contact us to help get your vulnerability management workflow streamlined!