cvss-rs 0.4.0

A Rust library for representing and deserializing CVSS (Common Vulnerability Scoring System) data.
Documentation
//! Lookup tables for CVSS v4.0 MacroVector scoring.
//!
//! Based on the official CVSS v4.0 specification and calculator:
//! <https://github.com/FIRSTdotorg/cvss-v4-calculator>

use super::scoring::{MacroVector, VectorEq};

/// MacroVector to base score lookup table.
///
/// Maps MacroVector tuples (EQ1-EQ6) to base scores according to the official CVSS v4.0 specification.
/// Returns None for invalid MacroVector combinations.
pub(crate) fn lookup_global(m: &MacroVector) -> Option<f64> {
    match m.as_tuple() {
        (0, 0, 0, 0, 0, 0) => Some(10.0),
        (0, 0, 0, 0, 0, 1) => Some(9.9),
        (0, 0, 0, 0, 1, 0) => Some(9.8),
        (0, 0, 0, 0, 1, 1) => Some(9.5),
        (0, 0, 0, 0, 2, 0) => Some(9.5),
        (0, 0, 0, 0, 2, 1) => Some(9.2),
        (0, 0, 0, 1, 0, 0) => Some(10.0),
        (0, 0, 0, 1, 0, 1) => Some(9.6),
        (0, 0, 0, 1, 1, 0) => Some(9.3),
        (0, 0, 0, 1, 1, 1) => Some(8.7),
        (0, 0, 0, 1, 2, 0) => Some(9.1),
        (0, 0, 0, 1, 2, 1) => Some(8.1),
        (0, 0, 0, 2, 0, 0) => Some(9.3),
        (0, 0, 0, 2, 0, 1) => Some(9.0),
        (0, 0, 0, 2, 1, 0) => Some(8.9),
        (0, 0, 0, 2, 1, 1) => Some(8.0),
        (0, 0, 0, 2, 2, 0) => Some(8.1),
        (0, 0, 0, 2, 2, 1) => Some(6.8),
        (0, 0, 1, 0, 0, 0) => Some(9.8),
        (0, 0, 1, 0, 0, 1) => Some(9.5),
        (0, 0, 1, 0, 1, 0) => Some(9.5),
        (0, 0, 1, 0, 1, 1) => Some(9.2),
        (0, 0, 1, 0, 2, 0) => Some(9.0),
        (0, 0, 1, 0, 2, 1) => Some(8.4),
        (0, 0, 1, 1, 0, 0) => Some(9.3),
        (0, 0, 1, 1, 0, 1) => Some(9.2),
        (0, 0, 1, 1, 1, 0) => Some(8.9),
        (0, 0, 1, 1, 1, 1) => Some(8.1),
        (0, 0, 1, 1, 2, 0) => Some(8.1),
        (0, 0, 1, 1, 2, 1) => Some(6.5),
        (0, 0, 1, 2, 0, 0) => Some(8.8),
        (0, 0, 1, 2, 0, 1) => Some(8.0),
        (0, 0, 1, 2, 1, 0) => Some(7.8),
        (0, 0, 1, 2, 1, 1) => Some(7.0),
        (0, 0, 1, 2, 2, 0) => Some(6.9),
        (0, 0, 1, 2, 2, 1) => Some(4.8),
        (0, 0, 2, 0, 0, 1) => Some(9.2),
        (0, 0, 2, 0, 1, 1) => Some(8.2),
        (0, 0, 2, 0, 2, 1) => Some(7.2),
        (0, 0, 2, 1, 0, 1) => Some(7.9),
        (0, 0, 2, 1, 1, 1) => Some(6.9),
        (0, 0, 2, 1, 2, 1) => Some(5.0),
        (0, 0, 2, 2, 0, 1) => Some(6.9),
        (0, 0, 2, 2, 1, 1) => Some(5.5),
        (0, 0, 2, 2, 2, 1) => Some(2.7),
        (0, 1, 0, 0, 0, 0) => Some(9.9),
        (0, 1, 0, 0, 0, 1) => Some(9.7),
        (0, 1, 0, 0, 1, 0) => Some(9.5),
        (0, 1, 0, 0, 1, 1) => Some(9.2),
        (0, 1, 0, 0, 2, 0) => Some(9.2),
        (0, 1, 0, 0, 2, 1) => Some(8.5),
        (0, 1, 0, 1, 0, 0) => Some(9.5),
        (0, 1, 0, 1, 0, 1) => Some(9.1),
        (0, 1, 0, 1, 1, 0) => Some(9.0),
        (0, 1, 0, 1, 1, 1) => Some(8.3),
        (0, 1, 0, 1, 2, 0) => Some(8.4),
        (0, 1, 0, 1, 2, 1) => Some(7.1),
        (0, 1, 0, 2, 0, 0) => Some(9.2),
        (0, 1, 0, 2, 0, 1) => Some(8.1),
        (0, 1, 0, 2, 1, 0) => Some(8.2),
        (0, 1, 0, 2, 1, 1) => Some(7.1),
        (0, 1, 0, 2, 2, 0) => Some(7.2),
        (0, 1, 0, 2, 2, 1) => Some(5.3),
        (0, 1, 1, 0, 0, 0) => Some(9.5),
        (0, 1, 1, 0, 0, 1) => Some(9.3),
        (0, 1, 1, 0, 1, 0) => Some(9.2),
        (0, 1, 1, 0, 1, 1) => Some(8.5),
        (0, 1, 1, 0, 2, 0) => Some(8.5),
        (0, 1, 1, 0, 2, 1) => Some(7.3),
        (0, 1, 1, 1, 0, 0) => Some(9.2),
        (0, 1, 1, 1, 0, 1) => Some(8.2),
        (0, 1, 1, 1, 1, 0) => Some(8.0),
        (0, 1, 1, 1, 1, 1) => Some(7.2),
        (0, 1, 1, 1, 2, 0) => Some(7.0),
        (0, 1, 1, 1, 2, 1) => Some(5.9),
        (0, 1, 1, 2, 0, 0) => Some(8.4),
        (0, 1, 1, 2, 0, 1) => Some(7.0),
        (0, 1, 1, 2, 1, 0) => Some(7.1),
        (0, 1, 1, 2, 1, 1) => Some(5.2),
        (0, 1, 1, 2, 2, 0) => Some(5.0),
        (0, 1, 1, 2, 2, 1) => Some(3.0),
        (0, 1, 2, 0, 0, 1) => Some(8.6),
        (0, 1, 2, 0, 1, 1) => Some(7.5),
        (0, 1, 2, 0, 2, 1) => Some(5.2),
        (0, 1, 2, 1, 0, 1) => Some(7.1),
        (0, 1, 2, 1, 1, 1) => Some(5.2),
        (0, 1, 2, 1, 2, 1) => Some(2.9),
        (0, 1, 2, 2, 0, 1) => Some(6.3),
        (0, 1, 2, 2, 1, 1) => Some(2.9),
        (0, 1, 2, 2, 2, 1) => Some(1.7),
        (1, 0, 0, 0, 0, 0) => Some(9.8),
        (1, 0, 0, 0, 0, 1) => Some(9.5),
        (1, 0, 0, 0, 1, 0) => Some(9.4),
        (1, 0, 0, 0, 1, 1) => Some(8.7),
        (1, 0, 0, 0, 2, 0) => Some(9.1),
        (1, 0, 0, 0, 2, 1) => Some(8.1),
        (1, 0, 0, 1, 0, 0) => Some(9.4),
        (1, 0, 0, 1, 0, 1) => Some(8.9),
        (1, 0, 0, 1, 1, 0) => Some(8.6),
        (1, 0, 0, 1, 1, 1) => Some(7.4),
        (1, 0, 0, 1, 2, 0) => Some(7.7),
        (1, 0, 0, 1, 2, 1) => Some(6.4),
        (1, 0, 0, 2, 0, 0) => Some(8.7),
        (1, 0, 0, 2, 0, 1) => Some(7.5),
        (1, 0, 0, 2, 1, 0) => Some(7.4),
        (1, 0, 0, 2, 1, 1) => Some(6.3),
        (1, 0, 0, 2, 2, 0) => Some(6.3),
        (1, 0, 0, 2, 2, 1) => Some(4.9),
        (1, 0, 1, 0, 0, 0) => Some(9.4),
        (1, 0, 1, 0, 0, 1) => Some(8.9),
        (1, 0, 1, 0, 1, 0) => Some(8.8),
        (1, 0, 1, 0, 1, 1) => Some(7.7),
        (1, 0, 1, 0, 2, 0) => Some(7.6),
        (1, 0, 1, 0, 2, 1) => Some(6.7),
        (1, 0, 1, 1, 0, 0) => Some(8.6),
        (1, 0, 1, 1, 0, 1) => Some(7.6),
        (1, 0, 1, 1, 1, 0) => Some(7.4),
        (1, 0, 1, 1, 1, 1) => Some(5.8),
        (1, 0, 1, 1, 2, 0) => Some(5.9),
        (1, 0, 1, 1, 2, 1) => Some(5.0),
        (1, 0, 1, 2, 0, 0) => Some(7.2),
        (1, 0, 1, 2, 0, 1) => Some(5.7),
        (1, 0, 1, 2, 1, 0) => Some(5.7),
        (1, 0, 1, 2, 1, 1) => Some(5.2),
        (1, 0, 1, 2, 2, 0) => Some(5.2),
        (1, 0, 1, 2, 2, 1) => Some(2.5),
        (1, 0, 2, 0, 0, 1) => Some(8.3),
        (1, 0, 2, 0, 1, 1) => Some(7.0),
        (1, 0, 2, 0, 2, 1) => Some(5.4),
        (1, 0, 2, 1, 0, 1) => Some(6.5),
        (1, 0, 2, 1, 1, 1) => Some(5.8),
        (1, 0, 2, 1, 2, 1) => Some(2.6),
        (1, 0, 2, 2, 0, 1) => Some(5.3),
        (1, 0, 2, 2, 1, 1) => Some(2.1),
        (1, 0, 2, 2, 2, 1) => Some(1.3),
        (1, 1, 0, 0, 0, 0) => Some(9.5),
        (1, 1, 0, 0, 0, 1) => Some(9.0),
        (1, 1, 0, 0, 1, 0) => Some(8.8),
        (1, 1, 0, 0, 1, 1) => Some(7.6),
        (1, 1, 0, 0, 2, 0) => Some(7.6),
        (1, 1, 0, 0, 2, 1) => Some(7.0),
        (1, 1, 0, 1, 0, 0) => Some(9.0),
        (1, 1, 0, 1, 0, 1) => Some(7.7),
        (1, 1, 0, 1, 1, 0) => Some(7.5),
        (1, 1, 0, 1, 1, 1) => Some(6.2),
        (1, 1, 0, 1, 2, 0) => Some(6.1),
        (1, 1, 0, 1, 2, 1) => Some(5.3),
        (1, 1, 0, 2, 0, 0) => Some(7.7),
        (1, 1, 0, 2, 0, 1) => Some(6.6),
        (1, 1, 0, 2, 1, 0) => Some(6.8),
        (1, 1, 0, 2, 1, 1) => Some(5.9),
        (1, 1, 0, 2, 2, 0) => Some(5.2),
        (1, 1, 0, 2, 2, 1) => Some(3.0),
        (1, 1, 1, 0, 0, 0) => Some(8.9),
        (1, 1, 1, 0, 0, 1) => Some(7.8),
        (1, 1, 1, 0, 1, 0) => Some(7.6),
        (1, 1, 1, 0, 1, 1) => Some(6.7),
        (1, 1, 1, 0, 2, 0) => Some(6.2),
        (1, 1, 1, 0, 2, 1) => Some(5.8),
        (1, 1, 1, 1, 0, 0) => Some(7.4),
        (1, 1, 1, 1, 0, 1) => Some(5.9),
        (1, 1, 1, 1, 1, 0) => Some(5.7),
        (1, 1, 1, 1, 1, 1) => Some(5.7),
        (1, 1, 1, 1, 2, 0) => Some(4.7),
        (1, 1, 1, 1, 2, 1) => Some(2.3),
        (1, 1, 1, 2, 0, 0) => Some(6.1),
        (1, 1, 1, 2, 0, 1) => Some(5.2),
        (1, 1, 1, 2, 1, 0) => Some(5.7),
        (1, 1, 1, 2, 1, 1) => Some(2.9),
        (1, 1, 1, 2, 2, 0) => Some(2.4),
        (1, 1, 1, 2, 2, 1) => Some(1.6),
        (1, 1, 2, 0, 0, 1) => Some(7.1),
        (1, 1, 2, 0, 1, 1) => Some(5.9),
        (1, 1, 2, 0, 2, 1) => Some(3.0),
        (1, 1, 2, 1, 0, 1) => Some(5.8),
        (1, 1, 2, 1, 1, 1) => Some(2.6),
        (1, 1, 2, 1, 2, 1) => Some(1.5),
        (1, 1, 2, 2, 0, 1) => Some(2.3),
        (1, 1, 2, 2, 1, 1) => Some(1.3),
        (1, 1, 2, 2, 2, 1) => Some(0.6),
        (2, 0, 0, 0, 0, 0) => Some(9.3),
        (2, 0, 0, 0, 0, 1) => Some(8.7),
        (2, 0, 0, 0, 1, 0) => Some(8.6),
        (2, 0, 0, 0, 1, 1) => Some(7.2),
        (2, 0, 0, 0, 2, 0) => Some(7.5),
        (2, 0, 0, 0, 2, 1) => Some(5.8),
        (2, 0, 0, 1, 0, 0) => Some(8.6),
        (2, 0, 0, 1, 0, 1) => Some(7.4),
        (2, 0, 0, 1, 1, 0) => Some(7.4),
        (2, 0, 0, 1, 1, 1) => Some(6.1),
        (2, 0, 0, 1, 2, 0) => Some(5.6),
        (2, 0, 0, 1, 2, 1) => Some(3.4),
        (2, 0, 0, 2, 0, 0) => Some(7.0),
        (2, 0, 0, 2, 0, 1) => Some(5.4),
        (2, 0, 0, 2, 1, 0) => Some(5.2),
        (2, 0, 0, 2, 1, 1) => Some(4.0),
        (2, 0, 0, 2, 2, 0) => Some(4.0),
        (2, 0, 0, 2, 2, 1) => Some(2.2),
        (2, 0, 1, 0, 0, 0) => Some(8.5),
        (2, 0, 1, 0, 0, 1) => Some(7.5),
        (2, 0, 1, 0, 1, 0) => Some(7.4),
        (2, 0, 1, 0, 1, 1) => Some(5.5),
        (2, 0, 1, 0, 2, 0) => Some(6.2),
        (2, 0, 1, 0, 2, 1) => Some(5.1),
        (2, 0, 1, 1, 0, 0) => Some(7.2),
        (2, 0, 1, 1, 0, 1) => Some(5.7),
        (2, 0, 1, 1, 1, 0) => Some(5.5),
        (2, 0, 1, 1, 1, 1) => Some(4.1),
        (2, 0, 1, 1, 2, 0) => Some(4.6),
        (2, 0, 1, 1, 2, 1) => Some(1.9),
        (2, 0, 1, 2, 0, 0) => Some(5.3),
        (2, 0, 1, 2, 0, 1) => Some(3.6),
        (2, 0, 1, 2, 1, 0) => Some(3.4),
        (2, 0, 1, 2, 1, 1) => Some(1.9),
        (2, 0, 1, 2, 2, 0) => Some(1.9),
        (2, 0, 1, 2, 2, 1) => Some(0.8),
        (2, 0, 2, 0, 0, 1) => Some(6.4),
        (2, 0, 2, 0, 1, 1) => Some(5.1),
        (2, 0, 2, 0, 2, 1) => Some(2.0),
        (2, 0, 2, 1, 0, 1) => Some(4.7),
        (2, 0, 2, 1, 1, 1) => Some(2.1),
        (2, 0, 2, 1, 2, 1) => Some(1.1),
        (2, 0, 2, 2, 0, 1) => Some(2.4),
        (2, 0, 2, 2, 1, 1) => Some(0.9),
        (2, 0, 2, 2, 2, 1) => Some(0.4),
        (2, 1, 0, 0, 0, 0) => Some(8.8),
        (2, 1, 0, 0, 0, 1) => Some(7.5),
        (2, 1, 0, 0, 1, 0) => Some(7.3),
        (2, 1, 0, 0, 1, 1) => Some(5.3),
        (2, 1, 0, 0, 2, 0) => Some(6.0),
        (2, 1, 0, 0, 2, 1) => Some(5.0),
        (2, 1, 0, 1, 0, 0) => Some(7.3),
        (2, 1, 0, 1, 0, 1) => Some(5.5),
        (2, 1, 0, 1, 1, 0) => Some(5.9),
        (2, 1, 0, 1, 1, 1) => Some(4.0),
        (2, 1, 0, 1, 2, 0) => Some(4.1),
        (2, 1, 0, 1, 2, 1) => Some(2.0),
        (2, 1, 0, 2, 0, 0) => Some(5.4),
        (2, 1, 0, 2, 0, 1) => Some(4.3),
        (2, 1, 0, 2, 1, 0) => Some(4.5),
        (2, 1, 0, 2, 1, 1) => Some(2.2),
        (2, 1, 0, 2, 2, 0) => Some(2.0),
        (2, 1, 0, 2, 2, 1) => Some(1.1),
        (2, 1, 1, 0, 0, 0) => Some(7.5),
        (2, 1, 1, 0, 0, 1) => Some(5.5),
        (2, 1, 1, 0, 1, 0) => Some(5.8),
        (2, 1, 1, 0, 1, 1) => Some(4.5),
        (2, 1, 1, 0, 2, 0) => Some(4.0),
        (2, 1, 1, 0, 2, 1) => Some(2.1),
        (2, 1, 1, 1, 0, 0) => Some(6.1),
        (2, 1, 1, 1, 0, 1) => Some(5.1),
        (2, 1, 1, 1, 1, 0) => Some(4.8),
        (2, 1, 1, 1, 1, 1) => Some(1.8),
        (2, 1, 1, 1, 2, 0) => Some(2.0),
        (2, 1, 1, 1, 2, 1) => Some(0.9),
        (2, 1, 1, 2, 0, 0) => Some(4.6),
        (2, 1, 1, 2, 0, 1) => Some(1.8),
        (2, 1, 1, 2, 1, 0) => Some(1.7),
        (2, 1, 1, 2, 1, 1) => Some(0.7),
        (2, 1, 1, 2, 2, 0) => Some(0.8),
        (2, 1, 1, 2, 2, 1) => Some(0.2),
        (2, 1, 2, 0, 0, 1) => Some(5.3),
        (2, 1, 2, 0, 1, 1) => Some(2.4),
        (2, 1, 2, 0, 2, 1) => Some(1.4),
        (2, 1, 2, 1, 0, 1) => Some(2.4),
        (2, 1, 2, 1, 1, 1) => Some(1.2),
        (2, 1, 2, 1, 2, 1) => Some(0.5),
        (2, 1, 2, 2, 0, 1) => Some(1.0),
        (2, 1, 2, 2, 1, 1) => Some(0.3),
        (2, 1, 2, 2, 2, 1) => Some(0.1),
        _ => None,
    }
}

/// Returns the highest severity vector strings for a given Equivalence group.
///
/// These vectors represent the maximum severity possible within each EQ value
/// and are used in severity distance calculations.
pub(crate) fn max_composed(eq: VectorEq) -> Vec<&'static str> {
    match eq {
        VectorEq::Eq1(0) => vec!["AV:N/PR:N/UI:N/"],
        VectorEq::Eq1(1) => vec!["AV:A/PR:N/UI:N/", "AV:N/PR:L/UI:N/", "AV:N/PR:N/UI:P/"],
        VectorEq::Eq1(2) => vec!["AV:P/PR:N/UI:N/", "AV:A/PR:L/UI:P/"],
        VectorEq::Eq2(0) => vec!["AC:L/AT:N/"],
        VectorEq::Eq2(1) => vec!["AC:H/AT:N/", "AC:L/AT:P/"],
        VectorEq::Eq3Eq6(0, 0) => vec!["VC:H/VI:H/VA:H/CR:H/IR:H/AR:H/"],
        VectorEq::Eq3Eq6(0, 1) => vec![
            "VC:H/VI:H/VA:L/CR:M/IR:M/AR:H/",
            "VC:H/VI:H/VA:H/CR:M/IR:M/AR:M/",
        ],
        VectorEq::Eq3Eq6(1, 0) => vec![
            "VC:L/VI:H/VA:H/CR:H/IR:H/AR:H/",
            "VC:H/VI:L/VA:H/CR:H/IR:H/AR:H/",
        ],
        VectorEq::Eq3Eq6(1, 1) => vec![
            "VC:L/VI:H/VA:L/CR:H/IR:M/AR:H/",
            "VC:L/VI:H/VA:H/CR:H/IR:M/AR:M/",
            "VC:H/VI:L/VA:H/CR:M/IR:H/AR:M/",
            "VC:H/VI:L/VA:L/CR:M/IR:H/AR:H/",
            "VC:L/VI:L/VA:H/CR:H/IR:H/AR:M/",
        ],
        VectorEq::Eq3Eq6(2, 1) => vec!["VC:L/VI:L/VA:L/CR:H/IR:H/AR:H/"],
        VectorEq::Eq4(0) => vec!["SC:H/SI:S/SA:S/"],
        VectorEq::Eq4(1) => vec!["SC:H/SI:H/SA:H/"],
        VectorEq::Eq4(2) => vec!["SC:L/SI:L/SA:L/"],
        VectorEq::Eq5(0) => vec!["E:A/"],
        VectorEq::Eq5(1) => vec!["E:P/"],
        VectorEq::Eq5(2) => vec!["E:U/"],
        _ => panic!("Unexpected vector: {:?}", eq),
    }
}

/// Returns the maximum severity distance for a given Equivalence group.
///
/// Used to normalize severity distance calculations by providing the maximum
/// possible distance within each EQ.
pub(crate) fn max_severity(eq: VectorEq) -> u8 {
    match eq {
        VectorEq::Eq1(0) => 1,
        VectorEq::Eq1(1) => 4,
        VectorEq::Eq1(2) => 5,
        VectorEq::Eq2(0) => 1,
        VectorEq::Eq2(1) => 2,
        VectorEq::Eq3Eq6(0, 0) => 7,
        VectorEq::Eq3Eq6(0, 1) => 6,
        VectorEq::Eq3Eq6(1, 0) => 8,
        VectorEq::Eq3Eq6(1, 1) => 8,
        VectorEq::Eq3Eq6(2, 1) => 10,
        VectorEq::Eq4(0) => 6,
        VectorEq::Eq4(1) => 5,
        VectorEq::Eq4(2) => 4,
        VectorEq::Eq5(0) => 1,
        VectorEq::Eq5(1) => 1,
        VectorEq::Eq5(2) => 1,
        _ => panic!("Unexpected vector: {:?}", eq),
    }
}