use libcvss::v2::base::{ AccessComplexity, AccessVector, Authentication, AvailabilityImpact, BaseVector, ConfidentialityImpact, IntegrityImpact, }; use libcvss::v2::environmental::{ AvailabilityRequirement, CollateralDamagePotential, ConfidentialityRequirement, EnvironmentalVector, IntegrityRequirement, TargetDistribution, }; use libcvss::v2::temporal::Exploitability::ProofOfConcept; use libcvss::v2::temporal::RemediationLevel::OfficialFix; use libcvss::v2::temporal::ReportConfidence::Confirmed; use libcvss::v2::temporal::{Exploitability, RemediationLevel, ReportConfidence, TemporalVector}; use libcvss::v2::CVSS2Vector; // These test cases are based on the official CVSS 2.0 examples // Examples are given with two environmental scores, one with collateral damage potential and target distribution set to None, and another to High. // Test cases includes both situations. struct TestCase { cvss_vector: CVSS2Vector, base_score: f64, temporal_score: f64, environmental_score_when_none: f64, environmental_score_when_high: f64, cvss_base_string: &'static str, cvss_full_string: &'static str, // Computed using https://nvd.nist.gov/vuln-metrics/cvss/v2-calculator?calculator } #[test] pub fn cvss_2_examples() { let test_cases = vec![cve_2002_0392(), cve_2003_0062(), cve_2003_0818()]; for test_case in test_cases { validate_test_case(&test_case); } } fn validate_test_case(test_case: &TestCase) { // Full CVSS string formatting assert_eq!( test_case.cvss_full_string, format!("{}", test_case.cvss_vector) ); // Full CVSS string parsing assert_eq!( Ok(test_case.cvss_vector), CVSS2Vector::parse_strict(test_case.cvss_full_string) ); assert_eq!( Ok(test_case.cvss_vector), CVSS2Vector::parse_nonstrict(test_case.cvss_full_string) ); // Scoring with environmental values set to None assert_eq!( test_case.environmental_score_when_none, test_case.cvss_vector.score() ); // Scoring with environmnental values set to High let mut cvvs_vector_with_high = test_case.cvss_vector.clone(); cvvs_vector_with_high.environmental = Some(EnvironmentalVector { collateral_damage_potential: Some(CollateralDamagePotential::High), target_distribution: Some(TargetDistribution::High), confidentiality_requirement: test_case .cvss_vector .environmental .unwrap() .confidentiality_requirement .clone(), integrity_requirement: test_case .cvss_vector .environmental .unwrap() .integrity_requirement .clone(), availability_requirement: test_case .cvss_vector .environmental .unwrap() .availability_requirement .clone(), }); assert_eq!( test_case.environmental_score_when_high, cvvs_vector_with_high.score() ); let mut base_only = test_case.cvss_vector.clone(); base_only.temporal = None; base_only.environmental = None; // Base CVSS string formatting assert_eq!(test_case.cvss_base_string, format!("{}", base_only)); // Base CVSS string parsing assert_eq!( Ok(base_only), CVSS2Vector::parse_strict(test_case.cvss_base_string) ); // Scoring base vector assert_eq!(test_case.base_score, base_only.score()); let mut temporal_only = test_case.cvss_vector.clone(); temporal_only.environmental = None; // Scoring temporal vector assert_eq!(test_case.temporal_score, temporal_only.score()); } fn cve_2002_0392() -> TestCase { TestCase { cvss_vector: CVSS2Vector { base: BaseVector { access_vector: AccessVector::Network, access_complexity: AccessComplexity::Low, authentication: Authentication::None, confidentiality_impact: ConfidentialityImpact::None, integrity_impact: IntegrityImpact::None, availability_impact: AvailabilityImpact::Complete, }, temporal: Some(TemporalVector { exploitability: Some(Exploitability::Functional), remediation_level: Some(RemediationLevel::OfficialFix), report_confidence: Some(ReportConfidence::Confirmed), }), environmental: Some(EnvironmentalVector { collateral_damage_potential: Some(CollateralDamagePotential::None), target_distribution: Some(TargetDistribution::None), confidentiality_requirement: Some(ConfidentialityRequirement::Medium), integrity_requirement: Some(IntegrityRequirement::Medium), availability_requirement: Some(AvailabilityRequirement::High), }), }, base_score: 7.8, temporal_score: 6.4, environmental_score_when_none: 0.0, environmental_score_when_high: 9.2, // https://nvd.nist.gov/vuln-metrics/cvss/v2-calculator?calculator gives 9.1 here! cvss_base_string: "AV:N/AC:L/Au:N/C:N/I:N/A:C", cvss_full_string: "AV:N/AC:L/Au:N/C:N/I:N/A:C/E:F/RL:OF/RC:C/CDP:N/TD:N/CR:M/IR:M/AR:H", // Computed using https://nvd.nist.gov/vuln-metrics/cvss/v2-calculator?calculator } } fn cve_2003_0818() -> TestCase { TestCase { cvss_vector: CVSS2Vector { base: BaseVector { access_vector: AccessVector::Network, access_complexity: AccessComplexity::Low, authentication: Authentication::None, confidentiality_impact: ConfidentialityImpact::Complete, integrity_impact: IntegrityImpact::Complete, availability_impact: AvailabilityImpact::Complete, }, temporal: Some(TemporalVector { exploitability: Some(Exploitability::Functional), remediation_level: Some(RemediationLevel::OfficialFix), report_confidence: Some(ReportConfidence::Confirmed), }), environmental: Some(EnvironmentalVector { collateral_damage_potential: Some(CollateralDamagePotential::None), target_distribution: Some(TargetDistribution::None), confidentiality_requirement: Some(ConfidentialityRequirement::Medium), integrity_requirement: Some(IntegrityRequirement::Medium), availability_requirement: Some(AvailabilityRequirement::Low), }), }, base_score: 10.0, temporal_score: 8.3, environmental_score_when_none: 0.0, environmental_score_when_high: 9.0, cvss_base_string: "AV:N/AC:L/Au:N/C:C/I:C/A:C", cvss_full_string: "AV:N/AC:L/Au:N/C:C/I:C/A:C/E:F/RL:OF/RC:C/CDP:N/TD:N/CR:M/IR:M/AR:L", // Computed using https://nvd.nist.gov/vuln-metrics/cvss/v2-calculator?calculator } } fn cve_2003_0062() -> TestCase { TestCase { cvss_vector: CVSS2Vector { base: BaseVector { access_vector: AccessVector::Local, access_complexity: AccessComplexity::High, authentication: Authentication::None, confidentiality_impact: ConfidentialityImpact::Complete, integrity_impact: IntegrityImpact::Complete, availability_impact: AvailabilityImpact::Complete, }, temporal: Some(TemporalVector { exploitability: Some(ProofOfConcept), remediation_level: Some(OfficialFix), report_confidence: Some(Confirmed), }), environmental: Some(EnvironmentalVector { collateral_damage_potential: Some(CollateralDamagePotential::None), target_distribution: Some(TargetDistribution::None), confidentiality_requirement: Some(ConfidentialityRequirement::Medium), integrity_requirement: Some(IntegrityRequirement::Medium), availability_requirement: Some(AvailabilityRequirement::Medium), }), }, base_score: 6.2, temporal_score: 4.9, environmental_score_when_none: 0.0, environmental_score_when_high: 7.5, // https://nvd.nist.gov/vuln-metrics/cvss/v2-calculator?calculator gives 7.4 here! cvss_base_string: "AV:L/AC:H/Au:N/C:C/I:C/A:C", cvss_full_string: "AV:L/AC:H/Au:N/C:C/I:C/A:C/E:POC/RL:OF/RC:C/CDP:N/TD:N/CR:M/IR:M/AR:M", } }