|
#!/bin/bash |
|
|
|
# Security Audit Script for Node.js/Next.js Projects |
|
# Focuses on Code Execution Risks and File System Operations |
|
|
|
# Color codes for output |
|
RED='\033[0;31m' |
|
YELLOW='\033[1;33m' |
|
GREEN='\033[0;32m' |
|
BLUE='\033[0;34m' |
|
NC='\033[0m' # No Color |
|
|
|
# Counters |
|
HIGH_COUNT=0 |
|
MEDIUM_COUNT=0 |
|
|
|
# Configuration |
|
SCAN_DIR="${1:-.}" # Default to current directory if no arg provided |
|
EXCLUDE_DIRS="node_modules|.next|dist|build|.git|coverage" |
|
FILE_PATTERNS="\.(js|jsx|ts|tsx)$" |
|
|
|
# Output file for report |
|
REPORT_FILE="security-audit-report.txt" |
|
|
|
echo -e "${BLUE}================================================${NC}" |
|
echo -e "${BLUE}Security Audit: Code Execution & File System${NC}" |
|
echo -e "${BLUE}================================================${NC}" |
|
echo "" |
|
echo "Scanning directory: $SCAN_DIR" |
|
echo "Report will be saved to: $REPORT_FILE" |
|
echo "" |
|
|
|
# Initialize report file |
|
cat > "$REPORT_FILE" << EOF |
|
Security Audit Report |
|
Generated: $(date) |
|
Directory: $SCAN_DIR |
|
|
|
================================================ |
|
FINDINGS |
|
================================================ |
|
|
|
EOF |
|
|
|
# Function to print and log findings |
|
log_finding() { |
|
local severity=$1 |
|
local category=$2 |
|
local pattern=$3 |
|
local file=$4 |
|
local line_num=$5 |
|
local line_content=$6 |
|
|
|
if [ "$severity" = "HIGH" ]; then |
|
((HIGH_COUNT++)) |
|
echo -e "${RED}[HIGH]${NC} $category" |
|
else |
|
((MEDIUM_COUNT++)) |
|
echo -e "${YELLOW}[MEDIUM]${NC} $category" |
|
fi |
|
|
|
echo " Pattern: $pattern" |
|
echo " File: $file:$line_num" |
|
echo " Code: $line_content" |
|
echo "" |
|
|
|
# Log to file |
|
cat >> "$REPORT_FILE" << EOF |
|
[$severity] $category |
|
Pattern: $pattern |
|
File: $file:$line_num |
|
Code: $line_content |
|
|
|
EOF |
|
} |
|
|
|
# Function to search for patterns |
|
search_pattern() { |
|
local pattern=$1 |
|
local severity=$2 |
|
local category=$3 |
|
|
|
# Find all matching files, excluding specified directories |
|
# Use name patterns for macOS compatibility (BSD find) |
|
find "$SCAN_DIR" -type f \( -name "*.js" -o -name "*.jsx" -o -name "*.ts" -o -name "*.tsx" \) \ |
|
| grep -vE "$EXCLUDE_DIRS" \ |
|
| while read -r file; do |
|
# Search for pattern with line numbers |
|
grep -nE "$pattern" "$file" 2>/dev/null | while IFS=: read -r line_num line_content; do |
|
log_finding "$severity" "$category" "$pattern" "$file" "$line_num" "$line_content" |
|
done |
|
done |
|
} |
|
|
|
echo -e "${BLUE}Starting Code Execution Checks...${NC}" |
|
echo "" |
|
|
|
# ============================================ |
|
# CODE EXECUTION RISKS |
|
# ============================================ |
|
|
|
echo "Checking for eval() usage..." |
|
search_pattern '\beval\s*\(' "HIGH" "Code Execution: eval()" |
|
|
|
echo "Checking for Function constructor..." |
|
search_pattern 'new\s+Function\s*\(' "HIGH" "Code Execution: Function constructor" |
|
|
|
echo "Checking for child_process.exec..." |
|
search_pattern '(exec|execSync)\s*\(' "HIGH" "Code Execution: child_process exec" |
|
|
|
echo "Checking for child_process.spawn with shell option..." |
|
search_pattern 'spawn\s*\([^)]*shell\s*:\s*true' "HIGH" "Code Execution: spawn with shell:true" |
|
|
|
echo "Checking for VM module usage..." |
|
search_pattern '(runInNewContext|runInThisContext|runInContext)\s*\(' "HIGH" "Code Execution: VM module" |
|
|
|
echo "Checking for dynamic require()..." |
|
search_pattern 'require\s*\(\s*[^"'"'"']' "MEDIUM" "Code Execution: dynamic require()" |
|
|
|
echo "Checking for dynamic import()..." |
|
search_pattern 'import\s*\(\s*[^"'"'"']' "MEDIUM" "Code Execution: dynamic import()" |
|
|
|
echo "Checking for dangerouslySetInnerHTML..." |
|
search_pattern 'dangerouslySetInnerHTML' "MEDIUM" "Code Execution: dangerouslySetInnerHTML (XSS)" |
|
|
|
echo "Checking for setTimeout/setInterval with strings..." |
|
search_pattern '(setTimeout|setInterval)\s*\(\s*["\x27]' "MEDIUM" "Code Execution: setTimeout/setInterval with string" |
|
|
|
echo "" |
|
echo -e "${BLUE}Starting File System Checks...${NC}" |
|
echo "" |
|
|
|
# ============================================ |
|
# FILE SYSTEM OPERATIONS |
|
# ============================================ |
|
|
|
echo "Checking for fs.readFile operations..." |
|
search_pattern 'fs\.(readFile|readFileSync)\s*\(' "HIGH" "File System: readFile with potential path injection" |
|
|
|
echo "Checking for fs.writeFile operations..." |
|
search_pattern 'fs\.(writeFile|writeFileSync)\s*\(' "HIGH" "File System: writeFile with potential path injection" |
|
|
|
echo "Checking for fs.unlink operations..." |
|
search_pattern 'fs\.(unlink|unlinkSync)\s*\(' "HIGH" "File System: file deletion" |
|
|
|
echo "Checking for path traversal patterns..." |
|
search_pattern '\.\.[/\\]' "HIGH" "File System: potential path traversal (../)" |
|
|
|
echo "Checking for fs.createReadStream..." |
|
search_pattern 'fs\.createReadStream\s*\(' "HIGH" "File System: createReadStream" |
|
|
|
echo "Checking for fs.createWriteStream..." |
|
search_pattern 'fs\.createWriteStream\s*\(' "HIGH" "File System: createWriteStream" |
|
|
|
echo "Checking for __dirname concatenation..." |
|
search_pattern '__dirname\s*\+' "MEDIUM" "File System: __dirname concatenation without path.join" |
|
|
|
echo "Checking for process.cwd() concatenation..." |
|
search_pattern 'process\.cwd\(\)\s*\+' "MEDIUM" "File System: process.cwd() concatenation" |
|
|
|
echo "Checking for fs.readdir operations..." |
|
search_pattern 'fs\.(readdir|readdirSync)\s*\(' "MEDIUM" "File System: directory listing" |
|
|
|
echo "Checking for fs.existsSync operations..." |
|
search_pattern 'fs\.existsSync\s*\(' "MEDIUM" "File System: existsSync (info disclosure)" |
|
|
|
# ============================================ |
|
# SUMMARY |
|
# ============================================ |
|
|
|
echo "" |
|
echo -e "${BLUE}================================================${NC}" |
|
echo -e "${BLUE}AUDIT SUMMARY${NC}" |
|
echo -e "${BLUE}================================================${NC}" |
|
echo "" |
|
|
|
if [ $HIGH_COUNT -eq 0 ] && [ $MEDIUM_COUNT -eq 0 ]; then |
|
echo -e "${GREEN}✓ No security issues detected!${NC}" |
|
else |
|
echo -e "${RED}High Severity Issues: $HIGH_COUNT${NC}" |
|
echo -e "${YELLOW}Medium Severity Issues: $MEDIUM_COUNT${NC}" |
|
echo "" |
|
echo -e "${YELLOW}⚠ Please review all findings carefully.${NC}" |
|
echo -e "${YELLOW}⚠ Manual verification required for each match.${NC}" |
|
fi |
|
|
|
echo "" |
|
echo "Full report saved to: $REPORT_FILE" |
|
echo "" |
|
|
|
# Exit with error code if high severity issues found |
|
if [ $HIGH_COUNT -gt 0 ]; then |
|
exit 1 |
|
fi |
|
|
|
exit 0 |