Skip to content

🎯 Impact & Sensitivity ​

Single-vector analysis: given one *Cvss3x, which base metric moves the score the most? ImpactAnalysis shows per-value deltas, SensitivityAnalysis shows each metric's score swing, and FindMetricChangesToReachTarget proposes the smallest set of changes to reach a target score.

Synopsis ​

go
impacts, _   := cvss.ImpactAnalysis(cv)          // per-value deltas, sorted by |delta|
sensitivities, _ := cvss.SensitivityAnalysis(cv)  // min..max swing per metric
changes, _   := cvss.FindMetricChangesToReachTarget(cv, 7.0)

All three operate on the base score only (the 8 base metrics).

How It Works ​

All three functions clone the vector, swap one base metric value at a time, and re-score with a fresh Calculator. ImpactAnalysis records per-value deltas and sorts by max |delta|; SensitivityAnalysis records each metric's min/max; FindMetricChangesToReachTarget greedily picks the largest in-direction delta until the target is reached (tolerance 0.05).

Types ​

MetricImpact ​

FieldTypeMeaning
MetricstringShort name, e.g. "AV"
CurrentValstringCurrent short value
CurrentScorefloat64Current base score
ValueImpacts[]ValueImpactOne entry per alternative value

ValueImpact ​

FieldTypeMeaning
ValuestringAlternative short value
LongValuestringe.g. "Adjacent"
Scorefloat64Base score if this value were chosen
Deltafloat64Score - CurrentScore (positive = higher)
SeveritySeveritySeverity at that score

MetricSensitivity ​

FieldTypeMeaning
MetricstringShort name
MinScorefloat64Lowest base score across this metric's values
MaxScorefloat64Highest base score across this metric's values
BaseScorefloat64Current base score
ScoreSwingfloat64MaxScore - MinScore

MetricChange ​

FieldTypeMeaning
MetricstringShort name
FromstringOriginal value
TostringProposed value
Deltafloat64Score change
ResultScorefloat64Score after the change
SeveritySeveritySeverity after the change

Each type has a String() for readable output.

API Reference ​

go
func ImpactAnalysis(cv *Cvss3x) ([]MetricImpact, error)
func SensitivityAnalysis(cv *Cvss3x) ([]MetricSensitivity, error)
func FindMetricChangesToReachTarget(cv *Cvss3x, targetScore float64) ([]MetricChange, error)
  • ImpactAnalysis returns impacts sorted by the largest absolute delta (most influential metric first).
  • SensitivityAnalysis returns sensitivities sorted by ScoreSwing descending.
  • FindMetricChangesToReachTarget greedily picks, per metric in impact order, the value that moves toward targetScore by the largest step. Stops within a 0.05 tolerance. Returns nil if already within tolerance.

Only base metrics are explored

These functions iterate the 8 base metrics (AV, AC, PR, UI, S, C, I, A) and their legal values. Temporal and environmental metrics are not perturbed. Use SetMetricValue manually if you need to explore those.

FindMetricChangesToReachTarget is a heuristic

It applies one change at a time in impact order and re-reads the score after each. It does not guarantee the globally minimal set of changes, and may overshoot when metrics interact (e.g. Scope changes flip PR scoring).

Example ​

go
package main

import (
    "fmt"

    "github.com/scagogogo/cvss-skills/pkg/cvss"
    "github.com/scagogogo/cvss-skills/pkg/parser"
)

func main() {
    cv, _ := parser.ParseString("CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H")

    // Which metric moves the score the most?
    impacts, _ := cvss.ImpactAnalysis(cv)
    fmt.Println("most influential:", impacts[0].Metric, impacts[0].ValueImpacts)

    // Score swing per metric.
    for _, s := range must(cvss.SensitivityAnalysis(cv)) {
        fmt.Printf("%s: %.1f ~ %.1f (swing %.1f)\n",
            s.Metric, s.MinScore, s.MaxScore, s.ScoreSwing)
    }

    // How to drop to <= 6.9?
    changes, _ := cvss.FindMetricChangesToReachTarget(cv, 6.9)
    for _, c := range changes {
        fmt.Println(c.String())
    }
}

func must[T any](v T, err error) T { if err != nil { panic(err) }; return v }

Released under the MIT License.