Skip to content

Commit 21432b1

Browse files
authored
Merge pull request #92 from openSVM/copilot/fix-81
Fix critical security audit system issues: unsafe unwrap() calls, magic constants, and cross-platform compatibility
2 parents 05ccbea + e692581 commit 21432b1

File tree

3 files changed

+277
-116
lines changed

3 files changed

+277
-116
lines changed

src/utils/audit.rs

Lines changed: 83 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
66
use anyhow::{Context, Result};
77
use chrono::{DateTime, Utc};
8+
use rand::Rng;
89
use serde::{Deserialize, Serialize};
910
use std::collections::HashMap;
1011
use 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
2234
pub 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

Comments
 (0)