Skip to content

Instantly share code, notes, and snippets.

@guilsa
Last active December 19, 2025 02:07
Show Gist options
  • Select an option

  • Save guilsa/311f417b9c355bb3c9aa7c486363c86f to your computer and use it in GitHub Desktop.

Select an option

Save guilsa/311f417b9c355bb3c9aa7c486363c86f to your computer and use it in GitHub Desktop.
Node.js Security Audit Script

Security Audit Script - Usage Guide

About

Written with Claude Sonnet 4.5. Prompt:

I have a new Node/Next.js client project that I'm running locally. The codebase is unfamiliar to me, so I want to build a bash script to grep for potentially dangerous patterns and ensure nothing unsafe is being executed. Let's start by planning the script—don't write the code yet.

Quick Start

# Make the script executable
chmod +x security-audit.sh

# Run in current directory
./security-audit.sh

# Run in a specific directory
./security-audit.sh /path/to/your/project

What It Checks

Code Execution Risks (HIGH severity)

  • eval() usage
  • Function() constructor
  • child_process.exec() / execSync()
  • spawn() with shell: true
  • VM module methods

Code Execution Risks (MEDIUM severity)

  • Dynamic require() with variables
  • Dynamic import() with variables
  • dangerouslySetInnerHTML
  • setTimeout/setInterval with string arguments

File System Operations (HIGH severity)

  • fs.readFile/writeFile operations
  • fs.unlink (file deletion)
  • Path traversal patterns (../)
  • fs.createReadStream/WriteStream

File System Operations (MEDIUM severity)

  • __dirname concatenation (without path.join)
  • process.cwd() concatenation
  • fs.readdir operations
  • fs.existsSync

Output

The script provides:

  1. Console output with color-coded severity levels
  2. Report file (security-audit-report.txt) with all findings

Exit Codes

  • 0 - No high severity issues found
  • 1 - High severity issues detected (useful for CI/CD)

What Gets Scanned

  • Includes: .js, .jsx, .ts, .tsx files
  • Excludes: node_modules, .next, dist, build, .git, coverage

Important Notes

⚠️ This script finds POTENTIAL issues - manual review is required:

  • Not all matches are vulnerabilities (false positives)
  • Some patterns may be safe if input is validated
  • Context matters - review the surrounding code

Example Output

[HIGH] Code Execution: eval()
  Pattern: \beval\s*\(
  File: ./src/utils/parser.js:45
  Code:   const result = eval(userInput);

[MEDIUM] File System: __dirname concatenation without path.join
  Pattern: __dirname\s*\+
  File: ./src/config/paths.js:12
  Code:   const configPath = __dirname + '/config.json';

Next Steps After Running

  1. Review each finding in context
  2. Check if user input is properly validated/sanitized
  3. Look for safer alternatives (e.g., use execFile instead of exec)
  4. For file operations, ensure paths are normalized with path.join() or path.resolve()
  5. Consider using linting tools like ESLint with security plugins for ongoing monitoring

Customize

Edit the script to:

  • Add/remove patterns
  • Change severity levels
  • Modify excluded directories
  • Adjust file type patterns
#!/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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment