Unfixed vulnerabilities are now the way in. The 2025 Verizon DBIR, summarised by Infosecurity Magazine, put exploitation of a vulnerability as the initial vector in 20% of breaches, up 34% on the year, with edge devices rising from 3% to 22% of those cases, and third parties involved in 30% of breaches. The 2026 DBIR goes further: 31% of breaches now start with a software vulnerability, overtaking stolen credentials for the first time.
The same 2025 report measured the response: 54% of vulnerabilities fully remediated, at a median of 32 days. Debt that is not fixed does not age out on its own. A secrets detection vendor's 2025 report found that 70% of secrets leaked in 2022 were still valid in 2025.
Most engineering leaders know they carry security debt. Few can say how much, whether it grew last month, or which part of it matters. This post proposes four numbers that answer those questions, all computable from scan history you already have or can start saving today, and none of which need a dashboard product to produce.
Metric 1: open proven findings, by severity
Start with the count that can be acted on. Not every row a scanner prints is a bug: some are traced data flows with evidence, some are patterns that matched, some are questions the tool raised and could not answer. Counting all of them as debt inflates the number and teaches the team to ignore it.
Count the proven ones, by severity. In Vulkro each finding carries a disposition, and the Critical and High tiers are reserved for findings backed by a proof: a traced path, a verified secret, a matched advisory. The unproven are reported at Medium so they stay visible without counting as confirmed debt. The not-checked tier is worth its own line in your report, because the biggest class inside it is authorization; the 2025 CWE Top 25, drawn from 39,080 CVE records, moved Missing Authorization up five places to number four. A scanner that is honest about not deciding those is telling you where a human review belongs.
Read the number with the published precision in mind. On Vulkro's current blind holdout, the scanner found 79% of planted vulnerabilities (181 of 229) and flagged 26% of known-safe controls at Medium or above (39 of 152). So the Critical count is a lower bound on real debt, and the Medium count includes some noise. Both are still the same measurement every week, which is what makes a trend meaningful.
Metric 2: age of the oldest open Critical
A count hides time. Ten Criticals opened this week and ten that have sat for a year are the same number and a very different situation. The second number to report is the age, in days, of the oldest open Critical finding.
This is the metric that maps most directly to the DBIR's 32-day median. If your oldest Critical is 200 days old, you have a finding that has outlived six remediation cycles, and the question "why" usually has an organisational answer: no owner, a module nobody wants to touch, or a finding everyone believes is a false positive but nobody has closed with a reason. Each of those is fixable once named.
The data comes from saved scans. vulkro scan . --save records a trend snapshot to ~/.vulkro/scans.db, and vulkro history lists the recent saved scans. A finding's fingerprint is stable across runs, so the first saved scan where it appears is its birthday.
Metric 3: new minus fixed, per week
The third number is a slope. Each week, how many findings appeared that were not in the previous snapshot, and how many that were present have gone? New minus fixed is the rate at which debt grows or shrinks. A team can carry a large stock of debt and be in good shape if the slope is negative; a team with a small stock and a positive slope is in trouble it has not noticed yet.
This is the same quantity a ratchet gate enforces at the pull request, measured instead at the week. vulkro trends . --limit 10 shows finding counts across the last ten saved scans, which is enough to see the direction by eye and to compute the slope from the JSON. Report it next to the throughput numbers the team already tracks, because the point of the metric is that security debt can be paid down at a rate, like any other kind.
Metric 4: the share of dependency CVEs that are reachable
Dependency findings dominate raw counts and distort every other metric if they are not separated. A manifest with four hundred transitive packages will match dozens of advisories, most of them for functions your code never calls.
The fourth number is the fraction of matched dependency CVEs whose vulnerable symbol is actually reachable from your code. vulkro scan --reachable-only drops the unreachable ones from the output; --no-reachability-filter keeps the raw advisory severity for every match. Run both and divide. A ratio of 10% means that nine in ten of the dependency alerts the team was arguing about were never exploitable along any path in the application, and that the one in ten deserves the attention the other nine were consuming.
This metric is also where "third-party involvement in 30% of breaches" becomes concrete. The exposure is not the count of advisories; it is the reachable subset, and that is a number a leader can set a target for.
Collecting the four without a dashboard product
Everything above comes from the command line and a saved database. The working set:
vulkro scan . --save # every scheduled run; writes the snapshot
vulkro history # the saved scans, newest first
vulkro trends . --limit 10 # counts across the last ten snapshots
vulkro summary # the current state in one screen
vulkro scan . --top 5 # the "Fix these first" list for the standup--top <N> orders by risk rather than by severity alone, and vulkro explain --risk-model prints the formula it uses, so nobody has to take the ordering on faith. The scan reference and the explain reference cover both.
Teams that would rather see the same numbers across repositories get them in Vulkro Cloud, where issues persist across scans with owners and fix deadlines, dependency checks match new advisories daily between scans, and dependency search works across every repository; the Cloud overview describes each view. Salesforce teams have the equivalent in vulkro-sf compliance kpi.
What the numbers do not tell you
Four metrics from a scanner describe the debt a scanner can see. They say nothing about design flaws, business-logic errors, misconfigured infrastructure the scan did not read, or the authorization questions the not-checked tier flags and declines to decide. A falling Critical count is good news about one layer. Keep the limits in the report so the numbers are trusted when they are good and believed when they are bad.
What to do this week
- Add
--saveto the scheduled scan so snapshots start accumulating; the metrics need history. - Compute the four numbers once by hand from
history,trendsand the two reachability runs, and write them down with a date. - Pick an owner for the oldest open Critical and a date for it.
- Put new-minus-fixed on the same page as the delivery metrics the team already reviews.
To see what the trend and issue views look like with a few months of history, open the sample workspace. To start saving your own, start the 14-day trial.