Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c5472674a1 | |||
| 52dcadea46 | |||
| 056d23f4d6 | |||
| 7e4a269522 | |||
| 3d2278d470 | |||
| f9220d8a65 | |||
| c5a0fbf392 |
@@ -173,7 +173,7 @@ create_temp_session() {
|
|||||||
mkdir -p "$TEMP_SESSION_DIR"
|
mkdir -p "$TEMP_SESSION_DIR"
|
||||||
|
|
||||||
# Cleanup on exit
|
# Cleanup on exit
|
||||||
trap "rm -rf $TEMP_SESSION_DIR 2>/dev/null" EXIT INT TERM
|
trap '[ -n "$TEMP_SESSION_DIR" ] && rm -rf "$TEMP_SESSION_DIR" 2>/dev/null' EXIT INT TERM
|
||||||
}
|
}
|
||||||
|
|
||||||
# Ask user for confirmation
|
# Ask user for confirmation
|
||||||
@@ -217,6 +217,7 @@ format_bytes() {
|
|||||||
|
|
||||||
# Format seconds to human readable time
|
# Format seconds to human readable time
|
||||||
format_duration() {
|
format_duration() {
|
||||||
|
[ -z "$1" ] && return 1
|
||||||
local seconds=$1
|
local seconds=$1
|
||||||
local days=$((seconds / 86400))
|
local days=$((seconds / 86400))
|
||||||
local hours=$(((seconds % 86400) / 3600))
|
local hours=$(((seconds % 86400) / 3600))
|
||||||
@@ -236,6 +237,7 @@ format_duration() {
|
|||||||
|
|
||||||
# Check if command exists
|
# Check if command exists
|
||||||
command_exists() {
|
command_exists() {
|
||||||
|
[ -z "$1" ] && return 1
|
||||||
command -v "$1" >/dev/null 2>&1
|
command -v "$1" >/dev/null 2>&1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,12 +65,12 @@ acquire_lock() {
|
|||||||
local timeout=10
|
local timeout=10
|
||||||
local elapsed=0
|
local elapsed=0
|
||||||
|
|
||||||
while [ -f "$IP_REP_LOCK" ] && [ $elapsed -lt $timeout ]; do
|
while [ -f "$IP_REP_LOCK" ] && [ ${elapsed:-0} -lt $timeout ]; do
|
||||||
sleep 0.1
|
sleep 0.1
|
||||||
elapsed=$((elapsed + 1))
|
elapsed=$((elapsed + 1))
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ $elapsed -ge $timeout ]; then
|
if [ ${elapsed:-0} -ge $timeout ]; then
|
||||||
# Stale lock, remove it
|
# Stale lock, remove it
|
||||||
rm -f "$IP_REP_LOCK" 2>/dev/null
|
rm -f "$IP_REP_LOCK" 2>/dev/null
|
||||||
fi
|
fi
|
||||||
@@ -277,13 +277,13 @@ mark_ip_legitimate() {
|
|||||||
get_ip_reputation_category() {
|
get_ip_reputation_category() {
|
||||||
local score="$1"
|
local score="$1"
|
||||||
|
|
||||||
if [ $score -ge $REP_SCORE_CRITICAL ]; then
|
if [ ${score:-0} -ge $REP_SCORE_CRITICAL ]; then
|
||||||
echo "CRITICAL"
|
echo "CRITICAL"
|
||||||
elif [ $score -ge $REP_SCORE_HIGH ]; then
|
elif [ ${score:-0} -ge $REP_SCORE_HIGH ]; then
|
||||||
echo "HIGH"
|
echo "HIGH"
|
||||||
elif [ $score -ge $REP_SCORE_MEDIUM ]; then
|
elif [ ${score:-0} -ge $REP_SCORE_MEDIUM ]; then
|
||||||
echo "MEDIUM"
|
echo "MEDIUM"
|
||||||
elif [ $score -ge $REP_SCORE_LOW ]; then
|
elif [ ${score:-0} -ge $REP_SCORE_LOW ]; then
|
||||||
echo "LOW"
|
echo "LOW"
|
||||||
else
|
else
|
||||||
echo "SAFE"
|
echo "SAFE"
|
||||||
@@ -525,7 +525,7 @@ should_block_ip() {
|
|||||||
|
|
||||||
IFS='|' read -r _ _ rep_score _ _ _ _ _ _ <<< "$data"
|
IFS='|' read -r _ _ rep_score _ _ _ _ _ _ <<< "$data"
|
||||||
|
|
||||||
[ $rep_score -ge $threshold ] && return 0 # Should block
|
[ ${rep_score:-0} -ge $threshold ] && return 0 # Should block
|
||||||
return 1 # Should not block
|
return 1 # Should not block
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -120,6 +120,7 @@ declare -gA PROBLEM_PATTERNS=(
|
|||||||
|
|
||||||
# Map database to user and domain
|
# Map database to user and domain
|
||||||
map_database_to_user_domain() {
|
map_database_to_user_domain() {
|
||||||
|
[ -z "$1" ] && return 1
|
||||||
local db_name="$1"
|
local db_name="$1"
|
||||||
local map_file="${TEMP_SESSION_DIR}/db_user_domain_map.tmp"
|
local map_file="${TEMP_SESSION_DIR}/db_user_domain_map.tmp"
|
||||||
|
|
||||||
@@ -154,12 +155,14 @@ map_database_to_user_domain() {
|
|||||||
|
|
||||||
# Get database owner
|
# Get database owner
|
||||||
get_database_owner() {
|
get_database_owner() {
|
||||||
|
[ -z "$1" ] && return 1
|
||||||
local db_name="$1"
|
local db_name="$1"
|
||||||
map_database_to_user_domain "$db_name" | cut -d'|' -f2
|
map_database_to_user_domain "$db_name" | cut -d'|' -f2
|
||||||
}
|
}
|
||||||
|
|
||||||
# Get database domain
|
# Get database domain
|
||||||
get_database_domain() {
|
get_database_domain() {
|
||||||
|
[ -z "$1" ] && return 1
|
||||||
local db_name="$1"
|
local db_name="$1"
|
||||||
map_database_to_user_domain "$db_name" | cut -d'|' -f3
|
map_database_to_user_domain "$db_name" | cut -d'|' -f3
|
||||||
}
|
}
|
||||||
@@ -216,6 +219,7 @@ parse_slow_query_log() {
|
|||||||
|
|
||||||
# Identify plugin from table name
|
# Identify plugin from table name
|
||||||
identify_plugin_from_table() {
|
identify_plugin_from_table() {
|
||||||
|
[ -z "$1" ] && return 1
|
||||||
local table_name="$1"
|
local table_name="$1"
|
||||||
|
|
||||||
# Remove prefix to get base table name
|
# Remove prefix to get base table name
|
||||||
@@ -240,6 +244,7 @@ identify_plugin_from_table() {
|
|||||||
|
|
||||||
# Get table size
|
# Get table size
|
||||||
get_table_size() {
|
get_table_size() {
|
||||||
|
[ -z "$1" ] || [ -z "$2" ] && return 1
|
||||||
local db_name="$1"
|
local db_name="$1"
|
||||||
local table_name="$2"
|
local table_name="$2"
|
||||||
|
|
||||||
@@ -250,6 +255,7 @@ get_table_size() {
|
|||||||
|
|
||||||
# Get all tables for database
|
# Get all tables for database
|
||||||
get_database_tables() {
|
get_database_tables() {
|
||||||
|
[ -z "$1" ] && return 1
|
||||||
local db_name="$1"
|
local db_name="$1"
|
||||||
|
|
||||||
mysql -Ns "$db_name" -e "SHOW TABLES" 2>/dev/null
|
mysql -Ns "$db_name" -e "SHOW TABLES" 2>/dev/null
|
||||||
@@ -257,6 +263,7 @@ get_database_tables() {
|
|||||||
|
|
||||||
# Analyze table for issues
|
# Analyze table for issues
|
||||||
analyze_table_structure() {
|
analyze_table_structure() {
|
||||||
|
[ -z "$1" ] || [ -z "$2" ] && return 1
|
||||||
local db_name="$1"
|
local db_name="$1"
|
||||||
local table_name="$2"
|
local table_name="$2"
|
||||||
|
|
||||||
@@ -270,6 +277,7 @@ analyze_table_structure() {
|
|||||||
|
|
||||||
# Extract database from query
|
# Extract database from query
|
||||||
extract_database_from_query() {
|
extract_database_from_query() {
|
||||||
|
[ -z "$1" ] && return 1
|
||||||
local query="$1"
|
local query="$1"
|
||||||
|
|
||||||
# Try to extract from USE statement
|
# Try to extract from USE statement
|
||||||
@@ -289,6 +297,7 @@ extract_database_from_query() {
|
|||||||
|
|
||||||
# Extract tables from query
|
# Extract tables from query
|
||||||
extract_tables_from_query() {
|
extract_tables_from_query() {
|
||||||
|
[ -z "$1" ] && return 1
|
||||||
local query="$1"
|
local query="$1"
|
||||||
|
|
||||||
# Extract FROM and JOIN clauses
|
# Extract FROM and JOIN clauses
|
||||||
@@ -297,6 +306,7 @@ extract_tables_from_query() {
|
|||||||
|
|
||||||
# Analyze query performance with EXPLAIN
|
# Analyze query performance with EXPLAIN
|
||||||
explain_query() {
|
explain_query() {
|
||||||
|
[ -z "$1" ] || [ -z "$2" ] && return 1
|
||||||
local db_name="$1"
|
local db_name="$1"
|
||||||
local query="$2"
|
local query="$2"
|
||||||
local explain_file="${TEMP_SESSION_DIR}/explain_${db_name}_$$.tmp"
|
local explain_file="${TEMP_SESSION_DIR}/explain_${db_name}_$$.tmp"
|
||||||
@@ -324,6 +334,7 @@ explain_query() {
|
|||||||
|
|
||||||
# Analyze queries and identify problems
|
# Analyze queries and identify problems
|
||||||
analyze_queries_for_problems() {
|
analyze_queries_for_problems() {
|
||||||
|
[ -z "$1" ] && return 1
|
||||||
local query_file="$1"
|
local query_file="$1"
|
||||||
local problems_file="${TEMP_SESSION_DIR}/query_problems.tmp"
|
local problems_file="${TEMP_SESSION_DIR}/query_problems.tmp"
|
||||||
|
|
||||||
@@ -385,6 +396,7 @@ analyze_queries_for_problems() {
|
|||||||
|
|
||||||
# Generate plugin query statistics
|
# Generate plugin query statistics
|
||||||
generate_plugin_statistics() {
|
generate_plugin_statistics() {
|
||||||
|
[ -z "$1" ] && return 1
|
||||||
local problems_file="$1"
|
local problems_file="$1"
|
||||||
local stats_file="${TEMP_SESSION_DIR}/plugin_stats.tmp"
|
local stats_file="${TEMP_SESSION_DIR}/plugin_stats.tmp"
|
||||||
|
|
||||||
@@ -417,6 +429,7 @@ find_largest_tables() {
|
|||||||
|
|
||||||
# Check for bloated tables
|
# Check for bloated tables
|
||||||
check_table_bloat() {
|
check_table_bloat() {
|
||||||
|
[ -z "$1" ] || [ -z "$2" ] && return 1
|
||||||
local db_name="$1"
|
local db_name="$1"
|
||||||
local table_name="$2"
|
local table_name="$2"
|
||||||
|
|
||||||
@@ -442,6 +455,7 @@ check_table_bloat() {
|
|||||||
|
|
||||||
# Recommend fixes for common issues
|
# Recommend fixes for common issues
|
||||||
recommend_fix() {
|
recommend_fix() {
|
||||||
|
[ -z "$1" ] && return 1
|
||||||
local issue="$1"
|
local issue="$1"
|
||||||
local db_name="$2"
|
local db_name="$2"
|
||||||
local table_name="$3"
|
local table_name="$3"
|
||||||
@@ -485,6 +499,7 @@ recommend_fix() {
|
|||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
generate_summary_report() {
|
generate_summary_report() {
|
||||||
|
[ -z "$1" ] && return 1
|
||||||
local problems_file="$1"
|
local problems_file="$1"
|
||||||
|
|
||||||
print_banner "MySQL Query Analysis Summary"
|
print_banner "MySQL Query Analysis Summary"
|
||||||
|
|||||||
@@ -275,6 +275,7 @@ parse_fpm_pool_config() {
|
|||||||
|
|
||||||
# Get current FPM process count for a pool
|
# Get current FPM process count for a pool
|
||||||
get_fpm_process_count() {
|
get_fpm_process_count() {
|
||||||
|
[ -z "$1" ] && return 1
|
||||||
local pool_name="$1" # Usually username or domain
|
local pool_name="$1" # Usually username or domain
|
||||||
|
|
||||||
ps aux | grep -E "php-fpm.*pool\s+${pool_name}" | grep -v grep | wc -l
|
ps aux | grep -E "php-fpm.*pool\s+${pool_name}" | grep -v grep | wc -l
|
||||||
@@ -282,6 +283,7 @@ get_fpm_process_count() {
|
|||||||
|
|
||||||
# Get memory usage per FPM process for a pool
|
# Get memory usage per FPM process for a pool
|
||||||
get_fpm_memory_usage() {
|
get_fpm_memory_usage() {
|
||||||
|
[ -z "$1" ] && return 1
|
||||||
local pool_name="$1"
|
local pool_name="$1"
|
||||||
|
|
||||||
# Get average memory per process (in KB)
|
# Get average memory per process (in KB)
|
||||||
|
|||||||
@@ -261,6 +261,7 @@ get_cpanel_user_domains() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get_plesk_user_domains() {
|
get_plesk_user_domains() {
|
||||||
|
[ -z "$1" ] && return 1
|
||||||
local username="$1"
|
local username="$1"
|
||||||
|
|
||||||
if command_exists mysql && [ -f /etc/psa/.psa.shadow ]; then
|
if command_exists mysql && [ -f /etc/psa/.psa.shadow ]; then
|
||||||
@@ -269,6 +270,7 @@ get_plesk_user_domains() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get_interworx_user_domains() {
|
get_interworx_user_domains() {
|
||||||
|
[ -z "$1" ] && return 1
|
||||||
local username="$1"
|
local username="$1"
|
||||||
|
|
||||||
# Method 1: Use listaccounts.pex to get primary domain
|
# Method 1: Use listaccounts.pex to get primary domain
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ declare -a FINDINGS=()
|
|||||||
|
|
||||||
# Function to add finding
|
# Function to add finding
|
||||||
add_finding() {
|
add_finding() {
|
||||||
|
[ -z "$1" ] || [ -z "$2" ] && return 1
|
||||||
local severity="$1"
|
local severity="$1"
|
||||||
local title="$2"
|
local title="$2"
|
||||||
local details="$3"
|
local details="$3"
|
||||||
@@ -53,6 +54,7 @@ add_finding() {
|
|||||||
|
|
||||||
# Function to check if command exists
|
# Function to check if command exists
|
||||||
command_exists() {
|
command_exists() {
|
||||||
|
[ -z "$1" ] && return 1
|
||||||
command -v "$1" &>/dev/null
|
command -v "$1" &>/dev/null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ declare -a RECOMMENDATIONS=()
|
|||||||
|
|
||||||
# Function to add finding
|
# Function to add finding
|
||||||
add_finding() {
|
add_finding() {
|
||||||
|
[ -z "$1" ] || [ -z "$2" ] && return 1
|
||||||
local severity="$1"
|
local severity="$1"
|
||||||
local title="$2"
|
local title="$2"
|
||||||
local details="$3"
|
local details="$3"
|
||||||
@@ -54,6 +55,7 @@ add_finding() {
|
|||||||
|
|
||||||
# Function to check if command exists
|
# Function to check if command exists
|
||||||
command_exists() {
|
command_exists() {
|
||||||
|
[ -z "$1" ] && return 1
|
||||||
command -v "$1" &>/dev/null
|
command -v "$1" &>/dev/null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1263,7 +1263,7 @@ generate_report() {
|
|||||||
# Detect spikes (>2x average)
|
# Detect spikes (>2x average)
|
||||||
avg_traffic=$((total_requests / 24))
|
avg_traffic=$((total_requests / 24))
|
||||||
spike=""
|
spike=""
|
||||||
[ $count -gt $((avg_traffic * 2)) ] && spike=" SPIKE"
|
[ ${count:-0} -gt $((avg_traffic * 2)) ] && spike=" SPIKE"
|
||||||
|
|
||||||
# Strip leading zeros to avoid octal interpretation
|
# Strip leading zeros to avoid octal interpretation
|
||||||
hour_num=$((10#$hour))
|
hour_num=$((10#$hour))
|
||||||
|
|||||||
@@ -838,7 +838,7 @@ for scanner in "${AVAILABLE_SCANNERS[@]}"; do
|
|||||||
((SCANNERS_COMPLETED++))
|
((SCANNERS_COMPLETED++))
|
||||||
|
|
||||||
# Wait between scanners
|
# Wait between scanners
|
||||||
if [ $SCANNERS_COMPLETED -lt $TOTAL_SCANNERS ]; then
|
if [ ${SCANNERS_COMPLETED:-0} -lt $TOTAL_SCANNERS ]; then
|
||||||
echo "Waiting 3 seconds before next scanner..."
|
echo "Waiting 3 seconds before next scanner..."
|
||||||
sleep 3
|
sleep 3
|
||||||
fi
|
fi
|
||||||
@@ -906,18 +906,28 @@ done
|
|||||||
# Look for POST requests to the directory containing the infected file
|
# Look for POST requests to the directory containing the infected file
|
||||||
|
|
||||||
# Use system-detected log directory with control panel-specific search
|
# Use system-detected log directory with control panel-specific search
|
||||||
local log_search_cmd
|
|
||||||
if [ "$CONTROL_PANEL" = "interworx" ]; then
|
if [ "$CONTROL_PANEL" = "interworx" ]; then
|
||||||
# InterWorx: Search /home/*/var/*/logs/transfer.log (VERIFIED: uses 'transfer.log')
|
# InterWorx: Search /home/*/var/*/logs/transfer.log (VERIFIED: uses 'transfer.log')
|
||||||
log_search_cmd="find /home/*/var/*/logs -type f -name 'transfer.log' 2>/dev/null"
|
# Search last 7 days of logs for POST requests to this path
|
||||||
|
find /home/*/var/*/logs -type f -name 'transfer.log' 2>/dev/null | while read -r logfile; do
|
||||||
|
# Check if this log corresponds to the domain/user
|
||||||
|
grep -h "POST.*${filepath}" "$logfile" 2>/dev/null | tail -20 | while read -r logline; do
|
||||||
|
# Extract IP from Apache log line
|
||||||
|
local ip=$(echo "$logline" | awk '{print $1}')
|
||||||
|
if [ -n "$ip" ] && [[ "$ip" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||||
|
# Flag this IP in reputation database
|
||||||
|
if type flag_ip_attack &>/dev/null; then
|
||||||
|
flag_ip_attack "$ip" "RCE" 25 "Malware scanner: Uploaded $filename" >/dev/null 2>&1
|
||||||
|
echo " → Flagged IP: $ip (uploaded to $filepath)" >> "$LOG_DIR/flagged_ips.log"
|
||||||
|
((flagged_ips++))
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
done
|
||||||
elif [ -n "$SYS_LOG_DIR" ] && [ -d "$SYS_LOG_DIR" ]; then
|
elif [ -n "$SYS_LOG_DIR" ] && [ -d "$SYS_LOG_DIR" ]; then
|
||||||
# cPanel/Plesk: Use detected log directory
|
# cPanel/Plesk: Use detected log directory
|
||||||
log_search_cmd="find $SYS_LOG_DIR -type f -name '*.com' -o -name '*.net' -o -name '*.org' 2>/dev/null"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "$log_search_cmd" ]; then
|
|
||||||
# Search last 7 days of logs for POST requests to this path
|
# Search last 7 days of logs for POST requests to this path
|
||||||
eval "$log_search_cmd" | while read -r logfile; do
|
find "$SYS_LOG_DIR" -type f \( -name '*.com' -o -name '*.net' -o -name '*.org' \) 2>/dev/null | while read -r logfile; do
|
||||||
# Check if this log corresponds to the domain/user
|
# Check if this log corresponds to the domain/user
|
||||||
grep -h "POST.*${filepath}" "$logfile" 2>/dev/null | tail -20 | while read -r logline; do
|
grep -h "POST.*${filepath}" "$logfile" 2>/dev/null | tail -20 | while read -r logline; do
|
||||||
# Extract IP from Apache log line
|
# Extract IP from Apache log line
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ echo ""
|
|||||||
# Temporary files
|
# Temporary files
|
||||||
TEMP_DIR="/tmp/500-tracker-$$"
|
TEMP_DIR="/tmp/500-tracker-$$"
|
||||||
mkdir -p "$TEMP_DIR"
|
mkdir -p "$TEMP_DIR"
|
||||||
trap "rm -rf $TEMP_DIR" EXIT
|
trap '[ -n "$TEMP_DIR" ] && rm -rf "$TEMP_DIR"' EXIT
|
||||||
|
|
||||||
ERRORS_500="$TEMP_DIR/errors_500.txt"
|
ERRORS_500="$TEMP_DIR/errors_500.txt"
|
||||||
ERROR_DETAILS="$TEMP_DIR/error_details.txt"
|
ERROR_DETAILS="$TEMP_DIR/error_details.txt"
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ echo ""
|
|||||||
# Temporary files
|
# Temporary files
|
||||||
TEMP_DIR="/tmp/website-error-analysis-$$"
|
TEMP_DIR="/tmp/website-error-analysis-$$"
|
||||||
mkdir -p "$TEMP_DIR"
|
mkdir -p "$TEMP_DIR"
|
||||||
trap "rm -rf $TEMP_DIR" EXIT
|
trap '[ -n "$TEMP_DIR" ] && rm -rf "$TEMP_DIR"' EXIT
|
||||||
|
|
||||||
CRITICAL_ERRORS="$TEMP_DIR/critical.txt"
|
CRITICAL_ERRORS="$TEMP_DIR/critical.txt"
|
||||||
USER_IMPACT_ERRORS="$TEMP_DIR/user_impact.txt"
|
USER_IMPACT_ERRORS="$TEMP_DIR/user_impact.txt"
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ fi
|
|||||||
if [ "$TRACE_ERASER_AUTO" = "yes" ]; then
|
if [ "$TRACE_ERASER_AUTO" = "yes" ]; then
|
||||||
# Auto mode: quick cleanup, minimal output
|
# Auto mode: quick cleanup, minimal output
|
||||||
cd /root 2>/dev/null
|
cd /root 2>/dev/null
|
||||||
rm -rf "$SCRIPT_DIR" 2>/dev/null
|
[ -n "$SCRIPT_DIR" ] && rm -rf "$SCRIPT_DIR" 2>/dev/null
|
||||||
clear
|
clear
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${GREEN}✓ All traces removed${NC}"
|
echo -e "${GREEN}✓ All traces removed${NC}"
|
||||||
@@ -181,7 +181,7 @@ else
|
|||||||
echo ""
|
echo ""
|
||||||
echo "Removing toolkit directory..."
|
echo "Removing toolkit directory..."
|
||||||
cd /root
|
cd /root
|
||||||
rm -rf "$SCRIPT_DIR"
|
[ -n "$SCRIPT_DIR" ] && rm -rf "$SCRIPT_DIR"
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${GREEN}✓ Toolkit completely removed${NC}"
|
echo -e "${GREEN}✓ Toolkit completely removed${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
@@ -191,7 +191,7 @@ else
|
|||||||
echo -e "${GREEN}✓ History and logs cleaned${NC}"
|
echo -e "${GREEN}✓ History and logs cleaned${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Toolkit directory remains at: $SCRIPT_DIR"
|
echo "Toolkit directory remains at: $SCRIPT_DIR"
|
||||||
echo "You can manually remove it later with: rm -rf $SCRIPT_DIR"
|
echo "You can manually remove it later with: [ -n \"\$SCRIPT_DIR\" ] && rm -rf \"\$SCRIPT_DIR\""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
|
|||||||
@@ -318,6 +318,11 @@ echo "Issue: rm -rf with potentially empty variables = catastrophic data loss"
|
|||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
while IFS=: read -r file line_num line_content; do
|
while IFS=: read -r file line_num line_content; do
|
||||||
|
# Skip if it's in an echo/comment (documentation, not execution)
|
||||||
|
if echo "$line_content" | grep -qE '^\s*(echo|#)'; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
# Check for rm -rf $var patterns where var might be empty
|
# Check for rm -rf $var patterns where var might be empty
|
||||||
if echo "$line_content" | grep -qE 'rm\s+-[a-z]*r[a-z]*f.*\$[A-Z_]+[^/]|rm\s+-[a-z]*r[a-z]*f\s+/?\$'; then
|
if echo "$line_content" | grep -qE 'rm\s+-[a-z]*r[a-z]*f.*\$[A-Z_]+[^/]|rm\s+-[a-z]*r[a-z]*f\s+/?\$'; then
|
||||||
# Skip if it has proper validation ([ -n "$var" ] && rm ...)
|
# Skip if it has proper validation ([ -n "$var" ] && rm ...)
|
||||||
@@ -466,10 +471,41 @@ while read -r file; do
|
|||||||
# Get function name
|
# Get function name
|
||||||
func_name=$(echo "$func_line" | sed 's/^\s*//; s/(.*$//')
|
func_name=$(echo "$func_line" | sed 's/^\s*//; s/(.*$//')
|
||||||
|
|
||||||
# Check if function uses parameters
|
# Check if function uses parameters (exclude AWK/sed field references)
|
||||||
if grep -A 20 "^[[:space:]]*$func_name()" "$file" 2>/dev/null | grep -q '\$[1-9]'; then
|
# Get function body and filter out awk/sed commands before checking for $1-9
|
||||||
# Check if it validates them
|
func_body=$(grep -A 20 "^[[:space:]]*$func_name()" "$file" 2>/dev/null | grep -v 'awk\|sed' || true)
|
||||||
if ! grep -A 5 "^[[:space:]]*$func_name()" "$file" 2>/dev/null | grep -qE '\[\s*-[nz]\s*"\$[1-9]"|\[\s*\$#\s*-'; then
|
|
||||||
|
# Skip functions that only use $@ or $* (passthrough/wrapper functions)
|
||||||
|
if echo "$func_body" | grep -E '^\s*(echo|printf).*\$[@*]' | grep -qv '\$[1-9]'; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
if echo "$func_body" | grep -q '\$[1-9]'; then
|
||||||
|
# Skip if uses safe default pattern: ${1:-default}
|
||||||
|
if grep -A 5 "^[[:space:]]*$func_name()" "$file" 2>/dev/null | grep -qE '\$\{[1-9]:-'; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Skip if function doesn't actually use positional params (only uses local vars)
|
||||||
|
# Check first 10 lines of function - if all $1-9 are in local declarations only, skip
|
||||||
|
if ! echo "$func_body" | grep -v "local.*=" | grep -q '\$[1-9]'; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Skip simple echo/print wrapper functions (validation not needed for display)
|
||||||
|
# If function only uses params in echo/print statements, it's safe
|
||||||
|
if echo "$func_body" | grep -E "^\s*(echo|printf|print)" | grep -q '\$[1-9]'; then
|
||||||
|
if ! echo "$func_body" | grep -v -E "^\s*(echo|printf|print|local|#)" | grep -q '\$[1-9]'; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if it validates them (accepts both $1 and variable name patterns)
|
||||||
|
# Pattern 1: [ -z "$1" ] or [ -n "$1" ]
|
||||||
|
# Pattern 2: [ -z "$var_name" ] where var_name was assigned from $1
|
||||||
|
# Pattern 3: [ $# -lt 1 ] or similar
|
||||||
|
# Pattern 4: if [ ! -f "$1" ] - file existence checks count as validation
|
||||||
|
if ! grep -A 5 "^[[:space:]]*$func_name()" "$file" 2>/dev/null | grep -qE '\[\s*-[nzf]\s*"\$([1-9]|[a-zA-Z_][a-zA-Z0-9_]*)"\s*\]|\[\s*!\s*-[nzf]\s*|\[\s*\$#\s*-'; then
|
||||||
echo "HIGH|$file|$line_num|Function '$func_name' uses parameters without validation"
|
echo "HIGH|$file|$line_num|Function '$func_name' uses parameters without validation"
|
||||||
count_issue "HIGH"
|
count_issue "HIGH"
|
||||||
((count++))
|
((count++))
|
||||||
|
|||||||
Reference in New Issue
Block a user