use crate::manifest::{RuleCategory, Severity};
use crate::rules::{CertRule, RuleViolation};
use crate::utility::cert_c::ast_utils::get_node_text;
use tree_sitter::Node;
pub struct Api10C;
impl CertRule for Api10C {
fn rule_id(&self) -> &'static str {
"API10-C"
}
fn description(&self) -> &'static str {
"APIs should have security options enabled by default"
}
fn severity(&self) -> Severity {
Severity::Medium
}
fn category(&self) -> RuleCategory {
RuleCategory::Recommendation
}
fn cert_id(&self) -> &'static str {
"API10-C"
}
fn check(&self, node: &Node, source: &str) -> Vec<RuleViolation> {
let mut violations = Vec::new();
self.check_node(node, source, &mut violations);
violations
}
}
impl Api10C {
fn check_node(&self, node: &Node, source: &str, violations: &mut Vec<RuleViolation>) {
if node.kind() == "preproc_def" {
self.check_define(node, source, violations);
}
for i in 0..node.child_count() {
if let Some(child) = node.child(i) {
self.check_node(&child, source, violations);
}
}
}
fn check_define(&self, node: &Node, source: &str, violations: &mut Vec<RuleViolation>) {
if let Some(name_node) = node.child_by_field_name("name") {
let macro_name = get_node_text(&name_node, source);
let insecure_patterns = [
"TLS_VALIDATE_HOST", "TLS_DISABLE_V1_0", "TLS_DISABLE_V1_1", "VALIDATE_", "ENABLE_SECURITY", "DISABLE_INSECURE", ];
for pattern in &insecure_patterns {
if macro_name.contains(pattern) {
let start_point = node.start_position();
let _define_text = get_node_text(node, source);
violations.push(RuleViolation {
rule_id: self.rule_id().to_string(),
severity: Severity::Medium,
message: format!(
"API option '{}' requires explicit opt-in for security (insecure by default). \
Security features should be enabled by default, requiring explicit opt-out.",
macro_name
),
file_path: String::new(),
line: start_point.row + 1,
column: start_point.column + 1,
suggestion: Some(
"Rename to require explicit opt-out of security (e.g., 'DISABLE_HOST_VALIDATION' \
instead of 'VALIDATE_HOST', 'ENABLE_V1_0' instead of 'DISABLE_V1_0')"
.to_string(),
),
..Default::default()
});
break; }
}
}
}
}