| //! Tests for parsing RustSec advisories |
| |
| #![warn(rust_2018_idioms, unused_qualifications)] |
| |
| use rustsec::advisory::{Category, License}; |
| use std::path::Path; |
| |
| /// Load example advisory from the filesystem |
| fn load_advisory(case: &str) -> rustsec::Advisory { |
| rustsec::Advisory::load_file(Path::new(&format!( |
| "./tests/support/example_advisory_{case}.md" |
| ))) |
| .unwrap() |
| } |
| |
| /// Basic metadata |
| #[test] |
| fn parse_metadata() { |
| for advisory in &[load_advisory("v3"), load_advisory("v4")] { |
| assert_eq!(advisory.metadata.id.as_str(), "RUSTSEC-2001-2101"); |
| assert_eq!(advisory.metadata.package.as_str(), "base"); |
| assert_eq!(advisory.title(), "All your base are belong to us"); |
| assert_eq!( |
| advisory.description(), |
| "You have no chance to survive. Make your time." |
| ); |
| assert_eq!(advisory.metadata.date.as_str(), "2001-02-03"); |
| assert_eq!( |
| advisory.metadata.url.as_ref().unwrap().to_string(), |
| "https://www.youtube.com/watch?v=jQE66WA2s-A" |
| ); |
| |
| for (i, category) in [Category::CodeExecution, Category::PrivilegeEscalation] |
| .iter() |
| .enumerate() |
| { |
| assert_eq!(*category, advisory.metadata.categories[i]); |
| } |
| |
| for (i, kw) in ["how", "are", "you", "gentlemen"].iter().enumerate() { |
| assert_eq!(*kw, advisory.metadata.keywords[i].as_str()); |
| } |
| |
| assert_eq!(advisory.metadata.license, License::CcZero10); |
| } |
| |
| // Test fields specific to advisories imported from GitHub |
| let ghsa = load_advisory("v4_from_ghsa"); |
| assert_eq!(ghsa.metadata.license, License::CcBy40); |
| |
| // Test advisory with unknown license |
| let ghsa = load_advisory("v4_unknown_license"); |
| assert_eq!(ghsa.metadata.license, License::Other("MPL-2.0".to_string())); |
| } |
| |
| /// Parsing of impact metadata |
| #[test] |
| fn parse_affected() { |
| let affected = load_advisory("v3").affected.unwrap(); |
| assert_eq!(affected.arch[0], platforms::target::Arch::X86); |
| assert_eq!(affected.os[0], platforms::target::OS::Windows); |
| |
| let example_function = "base::belongs::All".parse().unwrap(); |
| let req = &affected.functions.get(&example_function).unwrap()[0]; |
| assert!(req.matches(&"1.2.2".parse().unwrap())); |
| assert!(!req.matches(&"1.2.3".parse().unwrap())); |
| } |
| |
| /// Parsing of other aliased advisory IDs |
| #[test] |
| fn parse_aliases() { |
| let alias = &load_advisory("v3").metadata.aliases[0]; |
| assert!(alias.is_cve()); |
| assert_eq!(alias.year().unwrap(), 2001); |
| } |
| |
| /// Parsing of CVSS v3.1 severity vector strings |
| #[test] |
| fn parse_cvss_vector_string() { |
| let advisory = load_advisory("v3"); |
| assert_eq!( |
| advisory.severity().unwrap(), |
| rustsec::advisory::Severity::Critical |
| ); |
| |
| let cvss = advisory.metadata.cvss.unwrap(); |
| assert_eq!(cvss.av.unwrap(), cvss::v3::base::AttackVector::Network); |
| assert_eq!(cvss.ac.unwrap(), cvss::v3::base::AttackComplexity::Low); |
| assert_eq!(cvss.pr.unwrap(), cvss::v3::base::PrivilegesRequired::None); |
| assert_eq!(cvss.ui.unwrap(), cvss::v3::base::UserInteraction::None); |
| assert_eq!(cvss.s.unwrap(), cvss::v3::base::Scope::Changed); |
| assert_eq!(cvss.c.unwrap(), cvss::v3::base::Confidentiality::High); |
| assert_eq!(cvss.i.unwrap(), cvss::v3::base::Integrity::High); |
| assert_eq!(cvss.a.unwrap(), cvss::v3::base::Availability::High); |
| assert_eq!(cvss.score().value(), 10.0); |
| } |
| |
| /// Parsing of patched version reqs |
| #[test] |
| fn parse_patched_version_reqs() { |
| let advisory = load_advisory("v3"); |
| let req = &advisory.versions.patched()[0]; |
| assert!(!req.matches(&"1.2.2".parse().unwrap())); |
| assert!(req.matches(&"1.2.3".parse().unwrap())); |
| assert!(req.matches(&"1.2.4".parse().unwrap())); |
| } |