Expand description
CVSS v2, v3, and v4 vector string parser and score calculator.
This crate includes:
- Three CVSS version-specific modules for parsing and scoring vector strings.
- A high-level API which abstracts over version-specific parsing and scoring differences.
§Basic Use
Parse a vector string:
let vec: Vector = "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H".parse()?;Calculate vector score:
let score = Score::from(vec);Get score severity:
let severity = Severity::from(score);Vectors, scores, and severities are very small (see “Internal Representation”):
assert_eq!(size_of::<Score>(), size_of::<u8>()); // 1 byte
assert_eq!(size_of::<Severity>(), size_of::<u8>()); // 1 byte
assert_eq!(size_of::<Vector>(), size_of::<u64>()); // 8 bytes§Examples
Parse vector strings:
// parse CVSS v2 vector string
let v2: Vector = "AV:N/AC:L/Au:N/C:C/I:C/A:C".parse()?;
// parse CVSS v3 vector string
let v3: Vector = "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H".parse()?;
// parse CVSS v4 vector string
let v4: Vector = "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H".parse()?;Get vector score:
// parse CVSS v4 vector string
let v: Vector = "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H".parse()?;
// get score
let score = Score::from(v);
// check result
assert_eq!(score, Score::from(10.0));Compare scores:
let a = Score::from(1.2); // first score
let b = Score::from(3.5); // second score
assert!(a < b); // compare scoresGet score severity:
let severity = Severity::from(Score::from(2.3));
assert_eq!(severity, Severity::Low);Compare severities:
let a = Severity::Low; // first severity
let b = Severity::High; // second severity
assert!(a < b); // compare severitiesGet metric from vector by name:
// parse CVSS v4 vector string
let v: Vector = "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H".parse()?;
// get metric
let metric = v.get(Name::V4(v4::Name::AttackVector))?;
// check result
assert_eq!(metric, Metric::V4(v4::Metric::AttackVector(v4::AttackVector::Network)));Iterate over vector metrics:
// parse CVSS v4 vector string
let v: Vector = "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H".parse()?;
// print metrics
for m in v {
println!("metric: {m}");
}Convert a version-agnostic vector to a version-specific vector to access version-specific behavior:
// parse CVSS v4 vector string
let v: Vector = "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H".parse()?;
// convert version-agnosic vector to a v4 vector
let v = v4::Vector::from(v);
// get nomenclature
assert_eq!(v4::Nomenclature::from(v), v4::Nomenclature::CvssB);Show that metrics are always sorted in specification order when
converting a Vector to a string. In other words, the original
metric order is not preserved:
// parse v3 vector string with PR metric BEFORE AV and AC metric
let v: Vector = "CVSS:3.1/PR:N/AV:N/AC:L/UI:N/S:U/C:H/I:H/A:H".parse()?;
// check result; output string has PR metric AFTER AV and AC metric
assert_eq!(v.to_string(), "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H");Show that metrics with a value of Not Defined (X) are omitted when
converting a Vector to a string:
// parse v3 vector string with MAV:X metric
let v: Vector = "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H/MAV:X".parse()?;
// check result; output string does NOT include MAV:X
assert_eq!(v.to_string(), "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H");§Internal Representation
A Vector is represented internally as a bit field
within a u64. Metric values are packed in the lower 60 bits
and the CVSS version is packed in the in the upper 4 bits:
| Bit Range | Description |
|---|---|
0..60 | Metric values |
60..64 | CVSS version |
The bit packing varies by CVSS version:
| Version | Module | Metric Bits | Unused Bits | Version Bits |
|---|---|---|---|---|
| CVSS v2 | polycvss::v2 | 0..32 | 32..60 | 60..64 |
| CVSS v3 | polycvss::v3 | 0..44 | 44..60 | 60..64 |
| CVSS v4 | polycvss::v4 | 0..59 | 59..60 | 60..64 |
See v2::Vector, v3::Vector, and v4::Vector for additional details.