use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
#[non_exhaustive]
pub enum FindingKind {
Vulnerability,
Misconfiguration,
Exposure,
TechDetect,
DefaultCredentials,
InfoDisclosure,
FileDiscovery,
SecretLeak,
MaliciousCode,
SupplyChain,
Unclassified,
Other,
}
impl FindingKind {
#[must_use]
pub fn is_actionable(&self) -> bool {
matches!(
self,
Self::Vulnerability | Self::DefaultCredentials | Self::SecretLeak | Self::MaliciousCode
)
}
#[must_use]
pub fn is_classified(&self) -> bool {
!matches!(self, Self::Unclassified)
}
#[must_use]
pub fn requires_severity_bump(&self) -> bool {
matches!(
self,
Self::DefaultCredentials | Self::SecretLeak | Self::MaliciousCode
)
}
#[must_use]
pub fn severity_floor(&self) -> crate::Severity {
match self {
Self::MaliciousCode | Self::DefaultCredentials => crate::Severity::High,
Self::Vulnerability | Self::SecretLeak | Self::SupplyChain => crate::Severity::Medium,
Self::Misconfiguration | Self::Exposure => crate::Severity::Low,
Self::InfoDisclosure
| Self::FileDiscovery
| Self::TechDetect
| Self::Other
| Self::Unclassified => crate::Severity::Info,
}
}
}
impl std::fmt::Display for FindingKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let s = match self {
Self::Vulnerability => "vulnerability",
Self::Misconfiguration => "misconfiguration",
Self::Exposure => "exposure",
Self::TechDetect => "tech-detect",
Self::DefaultCredentials => "default-credentials",
Self::InfoDisclosure => "info-disclosure",
Self::FileDiscovery => "file-discovery",
Self::SecretLeak => "secret-leak",
Self::MaliciousCode => "malicious-code",
Self::SupplyChain => "supply-chain",
Self::Unclassified => "unclassified",
Self::Other => "other",
};
f.write_str(s)
}
}
impl std::str::FromStr for FindingKind {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let normalised = s.to_lowercase().replace('_', "-");
match normalised.as_str() {
"vulnerability" => Ok(Self::Vulnerability),
"misconfiguration" => Ok(Self::Misconfiguration),
"exposure" => Ok(Self::Exposure),
"tech-detect" => Ok(Self::TechDetect),
"default-credentials" => Ok(Self::DefaultCredentials),
"info-disclosure" => Ok(Self::InfoDisclosure),
"file-discovery" => Ok(Self::FileDiscovery),
"secret-leak" => Ok(Self::SecretLeak),
"malicious-code" => Ok(Self::MaliciousCode),
"supply-chain" => Ok(Self::SupplyChain),
"unclassified" => Ok(Self::Unclassified),
"other" => Ok(Self::Other),
_ => Err(format!("unknown FindingKind `{s}`")),
}
}
}