55
66use anyhow:: { Context , Result } ;
77use chrono:: { DateTime , Utc } ;
8+ use rand:: Rng ;
89use serde:: { Deserialize , Serialize } ;
910use std:: collections:: HashMap ;
1011use std:: path:: Path ;
@@ -18,6 +19,17 @@ use crate::utils::diagnostics::{
1819 DiagnosticCoordinator , DiagnosticResults , IssueCategory , IssueSeverity ,
1920} ;
2021
22+ /// Helper function to safely create regex patterns in the audit system
23+ fn safe_regex_new ( pattern : & str ) -> Option < regex:: Regex > {
24+ match regex:: Regex :: new ( pattern) {
25+ Ok ( r) => Some ( r) ,
26+ Err ( e) => {
27+ log:: warn!( "Failed to compile regex pattern '{}': {}" , pattern, e) ;
28+ None
29+ }
30+ }
31+ }
32+
2133/// OpenAI API client for AI-powered analysis with rate limiting and retry logic
2234pub struct OpenAIClient {
2335 api_key : String ,
@@ -151,9 +163,16 @@ impl OpenAIClient {
151163 match self . try_analyze_finding ( finding) . await {
152164 Ok ( analysis) => return Ok ( analysis) ,
153165 Err ( e) if attempt < self . max_retries => {
154- let ( should_retry, delay ) = EnhancedAIErrorHandler :: get_retry_strategy ( & e) ;
166+ let ( should_retry, base_delay ) = EnhancedAIErrorHandler :: get_retry_strategy ( & e) ;
155167
156168 if should_retry {
169+ // Implement exponential backoff with attempt count
170+ let backoff_factor = 2_u64 . pow ( attempt as u32 ) ;
171+ let jitter = rand:: random :: < f64 > ( ) * 0.5 + 0.5 ; // Random factor between 0.5 and 1.0
172+ let delay = std:: time:: Duration :: from_millis (
173+ ( base_delay. as_millis ( ) as f64 * backoff_factor as f64 * jitter) as u64
174+ ) ;
175+
157176 log:: warn!(
158177 "AI analysis attempt {}/{} failed, retrying in {}ms: {}" ,
159178 attempt + 1 ,
@@ -1438,8 +1457,10 @@ impl AuditCoordinator {
14381457 ] ;
14391458
14401459 for pattern in & secret_patterns {
1441- if regex:: Regex :: new ( pattern) . unwrap ( ) . is_match ( content) {
1442- return true ;
1460+ if let Some ( regex) = safe_regex_new ( pattern) {
1461+ if regex. is_match ( content) {
1462+ return true ;
1463+ }
14431464 }
14441465 }
14451466 false
@@ -1532,7 +1553,8 @@ impl AuditCoordinator {
15321553 ] ;
15331554
15341555 for pattern in & command_patterns {
1535- if regex:: Regex :: new ( pattern) . unwrap ( ) . is_match ( content) {
1556+ if let Some ( regex) = safe_regex_new ( pattern) {
1557+ if regex. is_match ( content) {
15361558 findings. push ( AuditFinding {
15371559 id : format ! ( "OSVM-{:03}" , * finding_id) ,
15381560 title : "Potential command injection vulnerability" . to_string ( ) ,
@@ -1576,7 +1598,8 @@ impl AuditCoordinator {
15761598 ] ;
15771599
15781600 for pattern in & path_patterns {
1579- if regex:: Regex :: new ( pattern) . unwrap ( ) . is_match ( content) {
1601+ if let Some ( regex) = safe_regex_new ( pattern) {
1602+ if regex. is_match ( content) {
15801603 findings. push ( AuditFinding {
15811604 id : format ! ( "OSVM-{:03}" , * finding_id) ,
15821605 title : "Potential path traversal vulnerability" . to_string ( ) ,
@@ -1651,7 +1674,8 @@ impl AuditCoordinator {
16511674 ] ;
16521675
16531676 for pattern in & tls_bypass_patterns {
1654- if regex:: Regex :: new ( pattern) . unwrap ( ) . is_match ( content) {
1677+ if let Some ( regex) = safe_regex_new ( pattern) {
1678+ if regex. is_match ( content) {
16551679 findings. push ( AuditFinding {
16561680 id : format ! ( "OSVM-{:03}" , * finding_id) ,
16571681 title : "TLS certificate verification bypass" . to_string ( ) ,
@@ -6603,28 +6627,66 @@ This security audit provides a comprehensive assessment of the OSVM CLI applicat
66036627 }
66046628 Ok ( Err ( e) ) => Err ( anyhow:: anyhow!( "Git command failed: {}" , e) ) ,
66056629 Err ( _) => {
6606- // Timeout occurred, try to kill the process
6630+ // Timeout occurred, try to kill the process using safer cross-platform approach
66076631 log:: warn!(
6608- "Git command timed out after {:?}, attempting to terminate" ,
6609- timeout
6632+ "Git command timed out after {:?}, attempting to terminate process {}" ,
6633+ timeout,
6634+ child_id
66106635 ) ;
66116636
6612- // On Unix systems, try to kill the process
6613- #[ cfg( unix) ]
6614- {
6615- unsafe {
6616- libc:: kill ( child_id as i32 , libc:: SIGTERM ) ;
6617- }
6637+ // Cross-platform process termination using standard library methods
6638+ // This approach is safer than direct libc calls
6639+ if let Err ( e) = Self :: terminate_process_safely ( child_id) {
6640+ log:: error!( "Failed to terminate git process {}: {}" , child_id, e) ;
66186641 }
66196642
6620- // On Windows, there's no direct equivalent, but the process should
6621- // be cleaned up when the program exits
6622- #[ cfg( windows) ]
6623- {
6624- log:: warn!( "Process termination on Windows not implemented, process may continue running" ) ;
6643+ Err ( anyhow:: anyhow!( "Git command timed out after {:?}" , timeout) )
6644+ }
6645+ }
6646+ }
6647+
6648+ /// Safely terminate a process using cross-platform methods
6649+ fn terminate_process_safely ( process_id : u32 ) -> Result < ( ) > {
6650+ #[ cfg( unix) ]
6651+ {
6652+ use std:: process:: Command ;
6653+ // Use the kill command instead of unsafe libc calls
6654+ let output = Command :: new ( "kill" )
6655+ . arg ( "-TERM" )
6656+ . arg ( process_id. to_string ( ) )
6657+ . output ( ) ;
6658+
6659+ match output {
6660+ Ok ( result) if result. status . success ( ) => {
6661+ log:: info!( "Successfully terminated process {} using kill command" , process_id) ;
6662+ Ok ( ( ) )
66256663 }
6664+ Ok ( result) => {
6665+ let stderr = String :: from_utf8_lossy ( & result. stderr ) ;
6666+ Err ( anyhow:: anyhow!( "kill command failed: {}" , stderr) )
6667+ }
6668+ Err ( e) => Err ( anyhow:: anyhow!( "Failed to execute kill command: {}" , e) )
6669+ }
6670+ }
66266671
6627- Err ( anyhow:: anyhow!( "Git command timed out after {:?}" , timeout) )
6672+ #[ cfg( windows) ]
6673+ {
6674+ use std:: process:: Command ;
6675+ // Use taskkill on Windows for proper process termination
6676+ let output = Command :: new ( "taskkill" )
6677+ . args ( & [ "/F" , "/PID" , & process_id. to_string ( ) ] )
6678+ . output ( ) ;
6679+
6680+ match output {
6681+ Ok ( result) if result. status . success ( ) => {
6682+ log:: info!( "Successfully terminated process {} using taskkill" , process_id) ;
6683+ Ok ( ( ) )
6684+ }
6685+ Ok ( result) => {
6686+ let stderr = String :: from_utf8_lossy ( & result. stderr ) ;
6687+ Err ( anyhow:: anyhow!( "taskkill command failed: {}" , stderr) )
6688+ }
6689+ Err ( e) => Err ( anyhow:: anyhow!( "Failed to execute taskkill: {}" , e) )
66286690 }
66296691 }
66306692 }
0 commit comments