Skip to main content

libverify_core/controls/
code_scanning_alerts_resolved.rs

1use crate::control::{Control, ControlFinding, ControlId, builtin};
2use crate::evidence::EvidenceBundle;
3
4/// Validates that no high-or-above severity code scanning alerts are open.
5///
6/// Maps to SOC2 CC7.1: detect and remediate vulnerabilities in source code.
7/// Open high/critical code scanning alerts indicate known security weaknesses
8/// that could be exploited in production.
9///
10/// Evaluation:
11/// - **NotApplicable**: code scanning is not enabled
12/// - **Satisfied**: zero open high-or-above severity alerts
13/// - **Violated**: one or more open high-or-above severity alerts
14pub struct CodeScanningAlertsResolvedControl;
15
16impl Control for CodeScanningAlertsResolvedControl {
17    fn id(&self) -> ControlId {
18        builtin::id(builtin::CODE_SCANNING_ALERTS_RESOLVED)
19    }
20
21    fn description(&self) -> &'static str {
22        "All high-or-above severity code scanning alerts must be resolved"
23    }
24
25    fn evaluate(&self, evidence: &EvidenceBundle) -> Vec<ControlFinding> {
26        let posture = match ControlFinding::extract_posture(self.id(), evidence) {
27            Ok(p) => p,
28            Err(findings) => return findings,
29        };
30
31        if !posture.code_scanning_enabled {
32            return vec![ControlFinding::not_applicable(
33                self.id(),
34                "Code scanning is not enabled — alert resolution check is not applicable",
35            )];
36        }
37
38        if posture.open_high_severity_alerts == 0 {
39            vec![ControlFinding::satisfied(
40                self.id(),
41                "No open high-or-above severity code scanning alerts",
42                vec!["repository:code-scanning:alerts:clear".to_string()],
43            )]
44        } else {
45            vec![ControlFinding::violated(
46                self.id(),
47                format!(
48                    "{} open high-or-above severity code scanning alert(s) — \
49                     resolve before deploying to production",
50                    posture.open_high_severity_alerts
51                ),
52                vec![format!(
53                    "repository:code-scanning:alerts:open:{}",
54                    posture.open_high_severity_alerts
55                )],
56            )]
57        }
58    }
59}
60
61#[cfg(test)]
62mod tests {
63    use super::*;
64    use crate::control::ControlStatus;
65    use crate::evidence::{EvidenceGap, EvidenceState, RepositoryPosture};
66
67    fn posture(code_scanning: bool, open_alerts: u32) -> RepositoryPosture {
68        RepositoryPosture {
69            code_scanning_enabled: code_scanning,
70            open_high_severity_alerts: open_alerts,
71            ..Default::default()
72        }
73    }
74
75    fn bundle(state: EvidenceState<RepositoryPosture>) -> EvidenceBundle {
76        EvidenceBundle {
77            repository_posture: state,
78            ..Default::default()
79        }
80    }
81
82    #[test]
83    fn not_applicable_when_posture_not_applicable() {
84        let findings =
85            CodeScanningAlertsResolvedControl.evaluate(&bundle(EvidenceState::not_applicable()));
86        assert_eq!(findings[0].status, ControlStatus::NotApplicable);
87    }
88
89    #[test]
90    fn indeterminate_when_posture_missing() {
91        let findings =
92            CodeScanningAlertsResolvedControl.evaluate(&bundle(EvidenceState::missing(vec![
93                EvidenceGap::CollectionFailed {
94                    source: "github".to_string(),
95                    subject: "posture".to_string(),
96                    detail: "API error".to_string(),
97                },
98            ])));
99        assert_eq!(findings[0].status, ControlStatus::Indeterminate);
100    }
101
102    #[test]
103    fn not_applicable_when_code_scanning_disabled() {
104        let findings = CodeScanningAlertsResolvedControl
105            .evaluate(&bundle(EvidenceState::complete(posture(false, 0))));
106        assert_eq!(findings[0].status, ControlStatus::NotApplicable);
107        assert!(findings[0].rationale.contains("not enabled"));
108    }
109
110    #[test]
111    fn satisfied_when_no_open_alerts() {
112        let findings = CodeScanningAlertsResolvedControl
113            .evaluate(&bundle(EvidenceState::complete(posture(true, 0))));
114        assert_eq!(findings[0].status, ControlStatus::Satisfied);
115        assert!(findings[0].rationale.contains("No open"));
116    }
117
118    #[test]
119    fn violated_when_open_alerts_exist() {
120        let findings = CodeScanningAlertsResolvedControl
121            .evaluate(&bundle(EvidenceState::complete(posture(true, 3))));
122        assert_eq!(findings[0].status, ControlStatus::Violated);
123        assert!(findings[0].rationale.contains("3 open"));
124        assert!(findings[0].subjects[0].contains("open:3"));
125    }
126}