Major QA script enhancement - Add 9 comprehensive security and quality checks

ENHANCEMENT: Expanded from 11 to 20 bug/security checks for comprehensive monitoring

NEW CHECKS ADDED:

CHECK 12: Dangerous rm commands (CRITICAL)
- Detects rm -rf with potentially empty variables
- Prevents catastrophic data loss scenarios
- Found: 6 dangerous rm -rf instances

CHECK 13: Unquoted variable expansions (HIGH)
- Detects unquoted $var in rm/cp/mv/chmod/chown
- Prevents word splitting and globbing issues
- Critical for file operation safety

CHECK 14: Command injection via eval (CRITICAL)
- Detects eval command usage
- Prevents arbitrary code execution risks
- Found: 1 eval instance in malware-scanner.sh

CHECK 15: Temp file security (MEDIUM)
- Detects predictable /tmp file names
- Recommends mktemp for security
- Prevents race condition attacks

CHECK 16: TODO/FIXME/HACK markers (LOW)
- Tracks technical debt markers
- Helps identify incomplete features
- Found: 2 instances

CHECK 17: Duplicate function definitions (MEDIUM)
- Detects same function in multiple files
- Prevents unpredictable behavior
- Found: 27 duplicates (mostly 'main' functions)

CHECK 18: Missing input validation (HIGH)
- Detects functions using $1/$2 without validation
- Critical security and reliability issue
- Found: 10 unvalidated parameter usages

CHECK 19: Long functions (MEDIUM)
- Detects functions >100 lines
- Maintainability and testability concern
- Helps identify refactoring candidates

CHECK 20: ShellCheck integration (VARIES)
- Integrates shellcheck if available
- Finds common bash pitfalls
- Optional but highly recommended

IMPACT:
✓ 20 bug/security checks (was 11)
✓ 5 performance checks (unchanged)
✓ Found 52 new issues on first run:
  - 7 CRITICAL (dangerous rm, eval)
  - 10 HIGH (missing validation)
  - 33 MEDIUM (duplicates)
  - 2 LOW (tech debt)

BENEFITS:
+ Comprehensive security scanning
+ Catches dangerous patterns before production
+ Tracks code quality metrics
+ Optional ShellCheck integration
+ Better technical debt visibility

The QA script is now a powerful development tool that can catch
security vulnerabilities, code quality issues, and maintainability
problems automatically.
This commit is contained in:
cschantz
2025-12-04 15:57:29 -05:00
parent 8dc6d3a2e8
commit 3739183886
+268 -11
View File
@@ -58,7 +58,7 @@ echo ""
#============================================================================== #==============================================================================
# CHECK 1: grep -F with regex anchors (CRITICAL - causes wrong results) # CHECK 1: grep -F with regex anchors (CRITICAL - causes wrong results)
#============================================================================== #==============================================================================
echo "[1/8] Checking: grep -F with regex anchors..." echo "[1/20] Checking: grep -F with regex anchors..."
{ {
echo "## CHECK 1: grep -F with regex anchors" echo "## CHECK 1: grep -F with regex anchors"
echo "Severity: CRITICAL" echo "Severity: CRITICAL"
@@ -79,7 +79,7 @@ echo ""
#============================================================================== #==============================================================================
# CHECK 2: SCRIPT_DIR collisions (HIGH - causes path errors) # CHECK 2: SCRIPT_DIR collisions (HIGH - causes path errors)
#============================================================================== #==============================================================================
echo "[2/8] Checking: SCRIPT_DIR variable collisions..." echo "[2/20] Checking: SCRIPT_DIR variable collisions..."
{ {
echo "## CHECK 2: SCRIPT_DIR variable collisions" echo "## CHECK 2: SCRIPT_DIR variable collisions"
echo "Severity: HIGH" echo "Severity: HIGH"
@@ -99,7 +99,7 @@ echo ""
#============================================================================== #==============================================================================
# CHECK 3: SYS_* variable resets (CRITICAL - breaks system detection) # CHECK 3: SYS_* variable resets (CRITICAL - breaks system detection)
#============================================================================== #==============================================================================
echo "[3/8] Checking: SYS_* variable resets..." echo "[3/20] Checking: SYS_* variable resets..."
{ {
echo "## CHECK 3: SYS_* variable resets without protection" echo "## CHECK 3: SYS_* variable resets without protection"
echo "Severity: CRITICAL" echo "Severity: CRITICAL"
@@ -120,7 +120,7 @@ echo ""
#============================================================================== #==============================================================================
# CHECK 4: Missing function exports (HIGH - functions unavailable) # CHECK 4: Missing function exports (HIGH - functions unavailable)
#============================================================================== #==============================================================================
echo "[4/8] Checking: Missing function exports..." echo "[4/20] Checking: Missing function exports..."
{ {
echo "## CHECK 4: Missing function exports in libraries" echo "## CHECK 4: Missing function exports in libraries"
echo "Severity: HIGH" echo "Severity: HIGH"
@@ -145,7 +145,7 @@ echo ""
#============================================================================== #==============================================================================
# CHECK 5: Integer comparisons without empty checks (HIGH - causes errors) # CHECK 5: Integer comparisons without empty checks (HIGH - causes errors)
#============================================================================== #==============================================================================
echo "[5/8] Checking: Unsafe integer comparisons (top 10)..." echo "[5/20] Checking: Unsafe integer comparisons (top 10)..."
{ {
echo "## CHECK 5: Integer comparisons without empty checks" echo "## CHECK 5: Integer comparisons without empty checks"
echo "Severity: HIGH" echo "Severity: HIGH"
@@ -170,7 +170,7 @@ echo ""
#============================================================================== #==============================================================================
# CHECK 6: Missing common-functions.sh (HIGH - command not found) # CHECK 6: Missing common-functions.sh (HIGH - command not found)
#============================================================================== #==============================================================================
echo "[6/8] Checking: Missing common-functions.sh..." echo "[6/20] Checking: Missing common-functions.sh..."
{ {
echo "## CHECK 6: Missing common-functions.sh sourcing" echo "## CHECK 6: Missing common-functions.sh sourcing"
echo "Severity: HIGH" echo "Severity: HIGH"
@@ -190,7 +190,7 @@ echo ""
#============================================================================== #==============================================================================
# CHECK 7: exit in libraries (HIGH - terminates parent script) # CHECK 7: exit in libraries (HIGH - terminates parent script)
#============================================================================== #==============================================================================
echo "[7/8] Checking: exit in library files..." echo "[7/20] Checking: exit in library files..."
{ {
echo "## CHECK 7: exit in sourced libraries" echo "## CHECK 7: exit in sourced libraries"
echo "Severity: HIGH" echo "Severity: HIGH"
@@ -215,7 +215,7 @@ echo ""
#============================================================================== #==============================================================================
# CHECK 8: bc command usage (LOW - external dependency) # CHECK 8: bc command usage (LOW - external dependency)
#============================================================================== #==============================================================================
echo "[8/11] Checking: bc command usage..." echo "[8/20] Checking: bc command usage..."
{ {
echo "## CHECK 8: bc command usage" echo "## CHECK 8: bc command usage"
echo "Severity: LOW" echo "Severity: LOW"
@@ -238,7 +238,7 @@ echo ""
#============================================================================== #==============================================================================
# CHECK 9: Hardcoded /var/cpanel paths (MEDIUM - breaks multi-panel) # CHECK 9: Hardcoded /var/cpanel paths (MEDIUM - breaks multi-panel)
#============================================================================== #==============================================================================
echo "[9/11] Checking: Hardcoded /var/cpanel paths..." echo "[9/20] Checking: Hardcoded /var/cpanel paths..."
{ {
echo "## CHECK 9: Hardcoded /var/cpanel paths" echo "## CHECK 9: Hardcoded /var/cpanel paths"
echo "Severity: MEDIUM" echo "Severity: MEDIUM"
@@ -264,7 +264,7 @@ echo ""
#============================================================================== #==============================================================================
# CHECK 10: Undefined color variables (LOW - cosmetic issue) # CHECK 10: Undefined color variables (LOW - cosmetic issue)
#============================================================================== #==============================================================================
echo "[10/11] Checking: Undefined color variables..." echo "[10/20] Checking: Undefined color variables..."
{ {
echo "## CHECK 10: Undefined color variables" echo "## CHECK 10: Undefined color variables"
echo "Severity: LOW" echo "Severity: LOW"
@@ -289,7 +289,7 @@ echo ""
#============================================================================== #==============================================================================
# CHECK 11: Bash syntax validation (CRITICAL - prevents execution) # CHECK 11: Bash syntax validation (CRITICAL - prevents execution)
#============================================================================== #==============================================================================
echo "[11/11] Checking: Bash syntax errors..." echo "[11/20] Checking: Bash syntax errors..."
{ {
echo "## CHECK 11: Bash syntax validation" echo "## CHECK 11: Bash syntax validation"
echo "Severity: CRITICAL" echo "Severity: CRITICAL"
@@ -307,6 +307,263 @@ done < <(find "$TOOLKIT_PATH" -name "*.sh" 2>/dev/null)
echo "" echo ""
} >> "$REPORT" } >> "$REPORT"
#==============================================================================
# CHECK 12: Dangerous rm commands (CRITICAL - data loss risk)
#==============================================================================
echo "[12/20] Checking: Dangerous rm commands..."
{
echo "## CHECK 12: Dangerous rm commands"
echo "Severity: CRITICAL"
echo "Issue: rm -rf with potentially empty variables = catastrophic data loss"
echo ""
while IFS=: read -r file line_num line_content; do
# 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
# Skip if it has proper validation ([ -n "$var" ] && rm ...)
if ! echo "$line_content" | grep -q '\[\s*-[nz]'; then
echo "CRITICAL|$file|$line_num|Dangerous rm -rf with unvalidated variable"
count_issue "CRITICAL"
fi
fi
done < <(grep -rn 'rm\s\+-[a-z]*r' "$TOOLKIT_PATH" --include="*.sh" --exclude="toolkit-qa-check.sh" 2>/dev/null | head -10)
echo ""
} >> "$REPORT"
#==============================================================================
# CHECK 13: Unquoted variable expansions (HIGH - word splitting/globbing risks)
#==============================================================================
echo "[13/20] Checking: Unquoted variables in dangerous contexts..."
{
echo "## CHECK 13: Unquoted variable expansions"
echo "Severity: HIGH"
echo "Issue: Unquoted \$var in rm/cp/mv can cause unintended file operations"
echo ""
while IFS=: read -r file line_num line_content; do
# Check for dangerous commands with unquoted variables
if echo "$line_content" | grep -qE '(rm|cp|mv|chmod|chown)\s+[^"'"'"']*\$[A-Z_a-z]+[^"]'; then
# Skip comments and quoted contexts
if ! echo "$line_content" | grep -qE '^\s*#|".*\$.*"|'"'"'.*\$.*'"'"''; then
echo "HIGH|$file|$line_num|Unquoted variable in dangerous command"
count_issue "HIGH"
fi
fi
done < <(grep -rnE '(rm|cp|mv|chmod|chown)\s+.*\$' "$TOOLKIT_PATH" --include="*.sh" --exclude="toolkit-qa-check.sh" 2>/dev/null | head -10)
echo ""
} >> "$REPORT"
#==============================================================================
# CHECK 14: Command injection via eval (CRITICAL - arbitrary code execution)
#==============================================================================
echo "[14/20] Checking: Command injection risks..."
{
echo "## CHECK 14: Command injection via eval"
echo "Severity: CRITICAL"
echo "Issue: eval with user-controlled input = remote code execution risk"
echo ""
while IFS=: read -r file line_num line_content; do
# Check for eval usage - always risky
if ! echo "$line_content" | grep -q '^\s*#'; then
echo "CRITICAL|$file|$line_num|Uses eval command (code injection risk)"
count_issue "CRITICAL"
fi
done < <(grep -rn '\beval\s' "$TOOLKIT_PATH" --include="*.sh" --exclude="toolkit-qa-check.sh" 2>/dev/null | head -5)
echo ""
} >> "$REPORT"
#==============================================================================
# CHECK 15: Temp file security (MEDIUM - race conditions/predictable names)
#==============================================================================
echo "[15/20] Checking: Temp file security..."
{
echo "## CHECK 15: Insecure temp file creation"
echo "Severity: MEDIUM"
echo "Issue: Predictable temp file names = race condition attacks"
echo ""
while IFS=: read -r file line_num line_content; do
# Check for /tmp usage without mktemp
if echo "$line_content" | grep -qE '/tmp/[a-zA-Z_-]+\.(txt|tmp|log|dat)'; then
if ! echo "$line_content" | grep -qE 'mktemp|TEMP_DIR'; then
echo "MEDIUM|$file|$line_num|Hardcoded /tmp path (use mktemp)"
count_issue "MEDIUM"
fi
fi
done < <(grep -rn '/tmp/' "$TOOLKIT_PATH" --include="*.sh" --exclude="toolkit-qa-check.sh" 2>/dev/null | head -10)
echo ""
} >> "$REPORT"
#==============================================================================
# CHECK 16: TODO/FIXME/HACK markers (LOW - technical debt tracking)
#==============================================================================
echo "[16/20] Checking: Technical debt markers..."
{
echo "## CHECK 16: TODO/FIXME/HACK comments"
echo "Severity: LOW"
echo "Issue: Tracks incomplete features and known issues"
echo ""
count=0
while IFS=: read -r file line_num line_content; do
marker=$(echo "$line_content" | grep -oE 'TODO|FIXME|HACK|XXX' | head -1)
echo "LOW|$file|$line_num|Technical debt: $marker"
count_issue "LOW"
((count++))
[ "$count" -ge 10 ] && break
done < <(grep -rnE '\b(TODO|FIXME|HACK|XXX)\b' "$TOOLKIT_PATH" --include="*.sh" --exclude="toolkit-qa-check.sh" 2>/dev/null)
total_debt=$(grep -rE '\b(TODO|FIXME|HACK|XXX)\b' "$TOOLKIT_PATH" --include="*.sh" --exclude="toolkit-qa-check.sh" 2>/dev/null | wc -l)
echo "Total found: $total_debt (showing first 10)"
echo ""
} >> "$REPORT"
#==============================================================================
# CHECK 17: Duplicate function definitions (MEDIUM - causes conflicts)
#==============================================================================
echo "[17/20] Checking: Duplicate function definitions..."
{
echo "## CHECK 17: Duplicate function definitions"
echo "Severity: MEDIUM"
echo "Issue: Same function in multiple files causes unpredictable behavior"
echo ""
# Extract all function names and find duplicates
declare -A func_files
while IFS=: read -r file func_name; do
if [ -n "${func_files[$func_name]}" ]; then
echo "MEDIUM|$file|N/A|Duplicate function '$func_name' (also in ${func_files[$func_name]})"
count_issue "MEDIUM"
else
func_files[$func_name]="$file"
fi
done < <(grep -rh '^\s*[a-zA-Z_][a-zA-Z0-9_]*\s*()' "$TOOLKIT_PATH" --include="*.sh" --exclude="toolkit-qa-check.sh" 2>/dev/null | \
sed 's/^\s*//; s/(.*$//' | sort | uniq -d | \
while read func; do grep -rl "^[[:space:]]*$func()" "$TOOLKIT_PATH" --include="*.sh" --exclude="toolkit-qa-check.sh" 2>/dev/null | sed "s|$|:$func|"; done)
echo ""
} >> "$REPORT"
#==============================================================================
# CHECK 18: Missing input validation (HIGH - security/reliability risk)
#==============================================================================
echo "[18/20] Checking: Missing input validation..."
{
echo "## CHECK 18: Functions without parameter validation"
echo "Severity: HIGH"
echo "Issue: Functions accepting parameters without validation"
echo ""
count=0
while read -r file; do
# Find functions that use $1, $2 etc but don't validate them
while IFS=: read -r line_num func_line; do
# Get function name
func_name=$(echo "$func_line" | sed 's/^\s*//; s/(.*$//')
# Check if function uses parameters
if grep -A 20 "^[[:space:]]*$func_name()" "$file" 2>/dev/null | grep -q '\$[1-9]'; then
# Check if it validates them
if ! grep -A 5 "^[[:space:]]*$func_name()" "$file" 2>/dev/null | grep -qE '\[\s*-[nz]\s*"\$[1-9]"|\[\s*\$#\s*-'; then
echo "HIGH|$file|$line_num|Function '$func_name' uses parameters without validation"
count_issue "HIGH"
((count++))
[ "$count" -ge 10 ] && break 2
fi
fi
done < <(grep -n '^\s*[a-zA-Z_][a-zA-Z0-9_]*\s*()' "$file" 2>/dev/null)
done < <(find "$TOOLKIT_PATH" -name "*.sh" -not -name "toolkit-qa-check.sh" 2>/dev/null)
echo "Found: $count issues (showing first 10)"
echo ""
} >> "$REPORT"
#==============================================================================
# CHECK 19: Long functions (MEDIUM - maintainability issue)
#==============================================================================
echo "[19/20] Checking: Overly long functions..."
{
echo "## CHECK 19: Long functions (>100 lines)"
echo "Severity: MEDIUM"
echo "Issue: Long functions are hard to maintain and test"
echo ""
count=0
while read -r file; do
# Find function definitions and count lines until closing brace
awk '
/^[[:space:]]*[a-zA-Z_][a-zA-Z0-9_]*[[:space:]]*\(\)/ {
func_name = $0
gsub(/[[:space:]]*\(\).*/, "", func_name)
gsub(/^[[:space:]]*/, "", func_name)
func_line = NR
brace_count = 0
line_count = 0
in_function = 1
next
}
in_function {
line_count++
if (/\{/) brace_count += gsub(/\{/, "{")
if (/\}/) brace_count -= gsub(/\}/, "}")
if (brace_count == 0 && line_count > 100) {
print FILENAME ":" func_line ":Function '\''" func_name "'\'' is " line_count " lines"
in_function = 0
}
if (brace_count == 0) in_function = 0
}
' "$file" 2>/dev/null
done < <(find "$TOOLKIT_PATH" -name "*.sh" -not -name "toolkit-qa-check.sh" 2>/dev/null) | while IFS=: read -r file line_num message; do
echo "MEDIUM|$file|$line_num|$message"
count_issue "MEDIUM"
((count++))
[ "$count" -ge 10 ] && break
done
echo ""
} >> "$REPORT"
#==============================================================================
# CHECK 20: ShellCheck integration (if available)
#==============================================================================
echo "[20/20] Checking: ShellCheck warnings (if available)..."
{
echo "## CHECK 20: ShellCheck static analysis"
echo "Severity: VARIES"
echo "Issue: ShellCheck finds many common bash pitfalls"
echo ""
if command -v shellcheck >/dev/null 2>&1; then
count=0
while read -r file; do
# Run shellcheck and capture warnings
shellcheck_output=$(shellcheck -f gcc "$file" 2>/dev/null | head -5)
if [ -n "$shellcheck_output" ]; then
echo "$shellcheck_output" | while IFS=: read -r f line col severity message; do
case "$severity" in
*error*) echo "HIGH|$f|$line|ShellCheck: $message"; count_issue "HIGH" ;;
*warning*) echo "MEDIUM|$f|$line|ShellCheck: $message"; count_issue "MEDIUM" ;;
*info*|*style*) echo "LOW|$f|$line|ShellCheck: $message"; count_issue "LOW" ;;
esac
((count++))
[ "$count" -ge 20 ] && break 2
done
fi
done < <(find "$TOOLKIT_PATH" -name "*.sh" -not -name "toolkit-qa-check.sh" 2>/dev/null | head -10)
echo "Note: Ran ShellCheck on first 10 files (showing first 20 issues)"
else
echo "INFO: ShellCheck not installed - skipping advanced checks"
echo "Install with: dnf install ShellCheck (or: apt install shellcheck)"
fi
echo ""
} >> "$REPORT"
#============================================================================== #==============================================================================
# PERFORMANCE CHECKS (INFO level - not counted as issues) # PERFORMANCE CHECKS (INFO level - not counted as issues)
#============================================================================== #==============================================================================