From 5b3ecbb2ae3a3b4a9e9dafcaaa01f70036e6a895 Mon Sep 17 00:00:00 2001 From: cschantz Date: Mon, 22 Dec 2025 19:18:26 -0500 Subject: [PATCH] Fix CRITICAL: ImunifyAV scan detection bug - was scanning 0 files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: ImunifyAV scans were completing instantly with 0 files scanned because our monitoring logic was fundamentally broken. Root Cause: 1. We ran: imunify-antivirus malware on-demand start --path="/" & 2. This command returns IMMEDIATELY (doesn't block) 3. ImunifyAV starts scan asynchronously in its own background process 4. Our shell's $SCAN_PID exits right away (command finished) 5. Monitoring loop: while kill -0 $SCAN_PID exits immediately 6. We read results before scan actually started/finished 7. Result: 0 files scanned, scan marked as "stopped" Example of broken output: ✓ Scanned 0 files ⏱ Duration: 7s [ImunifyAV scan complete - Found: 0] This is WRONG - should scan thousands of files! The Fix: Changed from monitoring shell PID to monitoring scan STATUS: OLD (BROKEN): - imunify-antivirus ... & # Background the COMMAND - SCAN_PID=$! - while kill -0 $SCAN_PID # Check if command still running This fails because command exits immediately! NEW (FIXED): - imunify-antivirus ... # Run in foreground (returns immediately anyway) - while scan_running: - Poll: imunify-antivirus malware on-demand list - Check SCAN_STATUS field (running/completed/stopped/failed) - Check CREATED timestamp (is this our scan?) - Monitor until status = completed/stopped/failed This works because we monitor the actual scan, not the command! Changes Made: 1. Removed & from command execution (line 829) - Command returns immediately anyway - No need to background it 2. Changed monitoring from PID-based to status-based (lines 846-895) - Poll scan list every 3 seconds - Check SCAN_STATUS field (field 7) - Check CREATED timestamp to identify our scan - Exit loop when status changes to terminal state 3. Added proper status handling: - completed: Success, read results - stopped: Warning, scan incomplete - failed: Error, skip this path 4. Added scan stop on timeout (line 892) - imunify-antivirus malware on-demand stop --path="$path" - Cleanly stops runaway scans 5. Better timestamp validation (line 856) - Only monitor scans created after SCAN_START - Prevents reading old/wrong scan results Status Field Values: - running: Scan in progress - completed: Scan finished successfully - stopped: Scan was interrupted/stopped - failed: Scan encountered error Impact: BEFORE: ImunifyAV scanned 0 files (broken) AFTER: ImunifyAV will properly scan thousands of files Testing Needed: - Run full server scan with ImunifyAV - Verify file count increases during scan - Verify scan completes with realistic file counts - Check that progress updates appear --- modules/security/malware-scanner.sh | 74 ++++++++++++++++++----------- 1 file changed, 47 insertions(+), 27 deletions(-) diff --git a/modules/security/malware-scanner.sh b/modules/security/malware-scanner.sh index fa82686..2624704 100755 --- a/modules/security/malware-scanner.sh +++ b/modules/security/malware-scanner.sh @@ -825,30 +825,60 @@ for scanner in "${AVAILABLE_SCANNERS[@]}"; do echo " ⏳ Scanner: ImunifyAV (monitoring progress...)" echo "" - # Start scan in background - imunify-antivirus malware on-demand start --path="$path" &>> "$LOG_DIR/imunify.log" & - SCAN_PID=$! + # Start scan (ImunifyAV runs async, command returns immediately) + imunify-antivirus malware on-demand start --path="$path" &>> "$LOG_DIR/imunify.log" + START_EXIT=$? - # Monitor progress by polling scan list - sleep 2 # Give scan time to start + if [ $START_EXIT -ne 0 ]; then + log_message "ERROR: ImunifyAV scan failed to start for $path (exit code: $START_EXIT)" + echo " ✗ Scan failed to start for $path (check logs)" + continue + fi + + # Monitor progress by polling scan status + # ImunifyAV runs scans asynchronously, we poll the status + sleep 3 # Give scan time to initialize last_count=0 timeout_counter=0 max_timeout=7200 # 2 hour timeout + scan_running=true - while kill -0 $SCAN_PID 2>/dev/null; do - # Get current scan status + while [ "$scan_running" = true ]; do + # Get current scan status from most recent scan scan_info=$(imunify-antivirus malware on-demand list 2>/dev/null | tail -n +2 | head -1) + if [ -n "$scan_info" ]; then current_files=$(echo "$scan_info" | awk '{print $11}') - status=$(echo "$scan_info" | awk '{print $2}') + current_status=$(echo "$scan_info" | awk '{print $7}') # Field 7 is SCAN_STATUS + created_time=$(echo "$scan_info" | awk '{print $2}') # Field 2 is CREATED - if [[ "$current_files" =~ ^[0-9]+$ ]]; then - if [ "$current_files" != "$last_count" ]; then - elapsed=$(($(date +%s) - SCAN_START)) - printf "\r Files scanned: %s | Elapsed: %s | Status: %s " \ - "$current_files" "$(format_time $elapsed)" "$status" - last_count=$current_files - timeout_counter=0 + # Check if this is our scan (created after scan start) + if [ "$created_time" -ge "$SCAN_START" ]; then + # Check status + if [[ "$current_status" =~ ^(completed|stopped|failed)$ ]]; then + scan_running=false + echo "" # New line after progress + + if [ "$current_status" = "failed" ]; then + log_message "ERROR: ImunifyAV scan failed for $path" + echo " ✗ Scan failed for $path" + continue 2 + elif [ "$current_status" = "stopped" ]; then + log_message "WARNING: ImunifyAV scan was stopped for $path" + echo " ⚠️ Scan was stopped (may be incomplete)" + fi + break + fi + + # Update progress if file count changed + if [[ "$current_files" =~ ^[0-9]+$ ]]; then + if [ "$current_files" != "$last_count" ]; then + elapsed=$(($(date +%s) - SCAN_START)) + printf "\r Files scanned: %s | Elapsed: %s | Status: %s " \ + "$current_files" "$(format_time $elapsed)" "$current_status" + last_count=$current_files + timeout_counter=0 + fi fi fi fi @@ -856,24 +886,14 @@ for scanner in "${AVAILABLE_SCANNERS[@]}"; do sleep 3 timeout_counter=$((timeout_counter + 3)) if [ $timeout_counter -ge $max_timeout ]; then - kill $SCAN_PID 2>/dev/null log_message "ERROR: ImunifyAV scan timed out after 2 hours for $path" echo -e "\n ⏱️ Scan timed out (exceeded 2 hour limit)" + # Try to stop the scan + imunify-antivirus malware on-demand stop --path="$path" &>/dev/null continue 2 fi done - # Wait for scan to complete - wait $SCAN_PID - SCAN_EXIT=$? - echo "" # New line after progress - - if [ $SCAN_EXIT -ne 0 ]; then - log_message "ERROR: ImunifyAV scan failed for $path (exit code: $SCAN_EXIT)" - echo " ✗ Scan failed for $path (check logs)" - continue - fi - # Get final scan results LAST_SCAN=$(imunify-antivirus malware on-demand list 2>/dev/null | tail -n +2 | head -1) FILES_SCANNED=$(echo "$LAST_SCAN" | awk '{print $11}')