7a0da7932b
OSV-Scanner (Scheduled) / scan-scheduled (push) Failing after 0s
Create Release / test-gate (push) Has been cancelled
Create Release / release-gate (push) Has been cancelled
Create Release / ci-gate (push) Has been cancelled
Create Release / version-check (push) Has been cancelled
Create Release / e2e-test-gate (push) Has been cancelled
Create Release / responsive-test-gate (push) Has been cancelled
Create Release / compat-test-gate (push) Has been cancelled
Create Release / compose-integration-gate (push) Has been cancelled
Create Release / vulture-gate (push) Has been cancelled
Create Release / build (push) Has been cancelled
Create Release / provenance (push) Has been cancelled
Create Release / prerelease-docker (push) Has been cancelled
Create Release / publish-docker (push) Has been cancelled
Create Release / create-release (push) Has been cancelled
Create Release / cleanup-changelog (push) Has been cancelled
Create Release / trigger-pypi (push) Has been cancelled
Create Release / monitor-pypi (push) Has been cancelled
Create Release / Clean up orphan prerelease tags and signatures (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Has been cancelled
Docker Tests (Consolidated) / Accessibility Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Unit Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Example Tests (push) Has been cancelled
Docker Tests (Consolidated) / Production Image Smoke Test (push) Has been cancelled
Docker Tests (Consolidated) / Infrastructure Tests (push) Has been cancelled
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Has been cancelled
Backwards Compatibility / Verify Encryption Constants (push) Has been cancelled
Backwards Compatibility / PyPI Version Compatibility (push) Has been cancelled
Backwards Compatibility / Database Migration Tests (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Docker Tests (Consolidated) / detect-changes (push) Has been cancelled
Docker Tests (Consolidated) / Build Test Image (push) Has been cancelled
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Has been cancelled
595 lines
22 KiB
Bash
Executable File
595 lines
22 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# File Whitelist Security Check Script
|
|
# Enhanced security checks with comprehensive file type detection
|
|
|
|
set -euo pipefail
|
|
|
|
# Load allowed file patterns from shared whitelist (single source of truth)
|
|
REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || echo ".")"
|
|
WHITELIST_FILE="$REPO_ROOT/.file-whitelist.txt"
|
|
|
|
if [ ! -f "$WHITELIST_FILE" ]; then
|
|
echo "❌ Missing .file-whitelist.txt — cannot run whitelist check."
|
|
exit 1
|
|
fi
|
|
|
|
ALLOWED_PATTERNS=()
|
|
while IFS= read -r line; do
|
|
[[ -z "$line" || "$line" =~ ^[[:space:]]*# ]] && continue
|
|
ALLOWED_PATTERNS+=("$line")
|
|
done < "$WHITELIST_FILE"
|
|
|
|
# Load per-check ignore lists (exact paths to skip for specific checks)
|
|
IGNORE_ENV_FILES=()
|
|
IGNORE_ENV_FILE="$REPO_ROOT/.github/security/ignore-env-files.txt"
|
|
if [ -f "$IGNORE_ENV_FILE" ]; then
|
|
while IFS= read -r line; do
|
|
[[ -z "$line" || "$line" =~ ^[[:space:]]*# ]] && continue
|
|
IGNORE_ENV_FILES+=("$line")
|
|
done < "$IGNORE_ENV_FILE"
|
|
fi
|
|
|
|
IGNORE_SUSPICIOUS_FILETYPES=()
|
|
IGNORE_SUSPICIOUS_FILE="$REPO_ROOT/.github/security/ignore-suspicious-filetypes.txt"
|
|
if [ -f "$IGNORE_SUSPICIOUS_FILE" ]; then
|
|
while IFS= read -r line; do
|
|
[[ -z "$line" || "$line" =~ ^[[:space:]]*# ]] && continue
|
|
IGNORE_SUSPICIOUS_FILETYPES+=("$line")
|
|
done < "$IGNORE_SUSPICIOUS_FILE"
|
|
fi
|
|
|
|
# Get list of files to check
|
|
if [ "${CHECK_ALL_FILES:-}" = "true" ]; then
|
|
echo "🔍 Checking ALL tracked files (release gate mode)..."
|
|
CHANGED_FILES=$(git ls-files)
|
|
TOTAL_FILE_COUNT=$(echo "$CHANGED_FILES" | wc -l)
|
|
echo "📋 Found $TOTAL_FILE_COUNT tracked files to check"
|
|
elif [ "$GITHUB_EVENT_NAME" = "pull_request" ]; then
|
|
# For PRs: check all files that would be added/modified in the entire PR
|
|
echo "🔍 Checking files in PR from $GITHUB_BASE_REF to HEAD..."
|
|
|
|
CHANGED_FILES=$(git diff --name-only --diff-filter=AM origin/"$GITHUB_BASE_REF"..HEAD)
|
|
FILE_COUNT=$(echo "$CHANGED_FILES" | wc -l)
|
|
echo "📋 Found $FILE_COUNT changed files with git diff"
|
|
|
|
# Also get newly added files across all commits in the PR
|
|
# Use a more robust approach that handles edge cases
|
|
ALL_NEW_FILES=$(git log --name-only --pretty=format: --diff-filter=A origin/"$GITHUB_BASE_REF"..HEAD 2>/dev/null | grep -v '^$' | sort | uniq || echo "")
|
|
NEW_FILE_COUNT=$(echo "$ALL_NEW_FILES" | wc -w)
|
|
echo "📋 Found $NEW_FILE_COUNT newly added files with git log"
|
|
|
|
# Combine both lists and remove duplicates - handle empty ALL_NEW_FILES
|
|
if [ -n "$ALL_NEW_FILES" ]; then
|
|
CHANGED_FILES=$(echo -e "$CHANGED_FILES\n$ALL_NEW_FILES" | sort | uniq | grep -v '^$')
|
|
fi
|
|
TOTAL_FILE_COUNT=$(echo "$CHANGED_FILES" | wc -l)
|
|
echo "📋 Total unique files to check: $TOTAL_FILE_COUNT"
|
|
else
|
|
# For direct pushes: check files in the current commit
|
|
echo "🔍 Checking files in latest commit..."
|
|
CHANGED_FILES=$(git diff --name-only --diff-filter=AM HEAD~1..HEAD)
|
|
TOTAL_FILE_COUNT=$(echo "$CHANGED_FILES" | wc -l)
|
|
echo "📋 Found $TOTAL_FILE_COUNT files in direct push"
|
|
fi
|
|
|
|
echo "🔍 Running comprehensive security checks..."
|
|
echo ""
|
|
|
|
FILES_CHECKED=0
|
|
WHITELIST_VIOLATIONS=()
|
|
LARGE_FILES=()
|
|
BINARY_FILES=()
|
|
SUSPICIOUS_FILES=()
|
|
RESEARCH_DATA_VIOLATIONS=()
|
|
FLASK_SECRET_VIOLATIONS=()
|
|
ENV_FILE_VIOLATIONS=()
|
|
HIGH_ENTROPY_VIOLATIONS=()
|
|
HARDCODED_PATH_VIOLATIONS=()
|
|
HARDCODED_IP_VIOLATIONS=()
|
|
SUSPICIOUS_FILETYPE_VIOLATIONS=()
|
|
|
|
# Use improved file processing that handles spaces and special characters
|
|
while IFS= read -r file; do
|
|
[ -z "$file" ] && continue
|
|
|
|
# Skip deleted files
|
|
if [ ! -f "$file" ]; then
|
|
continue
|
|
fi
|
|
|
|
FILES_CHECKED=$((FILES_CHECKED + 1))
|
|
if [ $((FILES_CHECKED % 10)) -eq 0 ]; then
|
|
printf "."
|
|
fi
|
|
|
|
# 1. Whitelist check
|
|
ALLOWED=false
|
|
for pattern in "${ALLOWED_PATTERNS[@]}"; do
|
|
if echo "$file" | grep -qE "$pattern"; then
|
|
ALLOWED=true
|
|
break
|
|
fi
|
|
done
|
|
|
|
if [ "$ALLOWED" = "false" ]; then
|
|
WHITELIST_VIOLATIONS+=("$file")
|
|
fi
|
|
|
|
# 2. Large file check (>1MB)
|
|
if [ -f "$file" ]; then
|
|
FILE_SIZE=$(stat -c%s "$file" 2>/dev/null || echo 0)
|
|
if [ "$FILE_SIZE" -gt 1048576 ]; then
|
|
LARGE_FILES+=("$file ($(echo "$FILE_SIZE" | awk '{printf "%.1fMB", $1/1024/1024}'))")
|
|
fi
|
|
fi
|
|
|
|
# 3. Binary file check
|
|
if file "$file" | grep -q "binary"; then
|
|
BINARY_FILES+=("$file")
|
|
fi
|
|
|
|
# 4. Secret pattern check - REMOVED: gitleaks workflow handles this more accurately
|
|
|
|
# 5. Suspicious filename patterns - whitelist approach
|
|
SAFE_FILENAME_PATTERNS=(
|
|
".*token_counter.*\.py$"
|
|
".*migrate.*token.*\.py$"
|
|
".*enhanced.*token.*\.md$"
|
|
"docs/.*token.*\.md$"
|
|
"tests/.*\.py$"
|
|
"docs/decisions/.*\.md$"
|
|
".*session_passwords\.py$"
|
|
".*change_password\.html$"
|
|
"tests/ui_tests/.*password.*\.js$"
|
|
".*password_validator\.py$"
|
|
".*password_utils\.py$"
|
|
)
|
|
|
|
# Check if filename looks suspicious
|
|
if echo "$file" | grep -iE "(secret|password|token|\.key$|\.pem$|\.p12$|\.pfx$|\.env$)" >/dev/null; then
|
|
# Check if filename matches whitelist patterns
|
|
FILENAME_WHITELISTED=false
|
|
for pattern in "${SAFE_FILENAME_PATTERNS[@]}"; do
|
|
if echo "$file" | grep -qE "$pattern"; then
|
|
FILENAME_WHITELISTED=true
|
|
break
|
|
fi
|
|
done
|
|
|
|
if [ "$FILENAME_WHITELISTED" = "false" ]; then
|
|
SUSPICIOUS_FILES+=("$file")
|
|
fi
|
|
fi
|
|
|
|
# 6. LDR-specific security checks
|
|
# Check for research data leakage
|
|
if [ -f "$file" ] && [ -r "$file" ]; then
|
|
# Check for hardcoded research queries in non-test files
|
|
if ! echo "$file" | grep -qE "(test|mock|example)"; then
|
|
if grep -E "(research_id|session_id|query_id).*=.*[\"'][0-9a-f]{8,}[\"']" "$file" >/dev/null 2>&1; then
|
|
RESEARCH_DATA_VIOLATIONS+=("$file")
|
|
fi
|
|
fi
|
|
|
|
# Check for Flask secret keys
|
|
if grep -E "SECRET_KEY.*=.*[\"'][^\"']{16,}[\"']" "$file" >/dev/null 2>&1; then
|
|
if ! grep -iE "(os\.environ|getenv|config\[|example|placeholder)" "$file" >/dev/null 2>&1; then
|
|
FLASK_SECRET_VIOLATIONS+=("$file")
|
|
fi
|
|
fi
|
|
|
|
# Check for environment files
|
|
if echo "$file" | grep -E "\.(env|env\.[a-zA-Z]+)$" >/dev/null; then
|
|
ENV_IGNORED=false
|
|
for epath in "${IGNORE_ENV_FILES[@]+${IGNORE_ENV_FILES[@]}}"; do
|
|
[ "$file" = "$epath" ] && ENV_IGNORED=true && break
|
|
done
|
|
if [ "$ENV_IGNORED" = "false" ]; then
|
|
ENV_FILE_VIOLATIONS+=("$file")
|
|
fi
|
|
fi
|
|
|
|
# Check for high-entropy strings (potential keys/secrets)
|
|
if [ -f "$file" ] && [ -r "$file" ]; then
|
|
# Skip HTML files and other safe file types for entropy checks
|
|
if ! echo "$file" | grep -qE "\.(html|css|js|json|yml|yaml|md)$"; then
|
|
# Skip news_strategy.py which contains example categories in prompts
|
|
if ! echo "$file" | grep -qE "news_strategy\.py$"; then
|
|
# Look for base64-like strings or hex strings that are suspiciously long
|
|
if grep -E "[a-zA-Z0-9+/]{40,}={0,2}|[a-f0-9]{40,}" "$file" >/dev/null 2>&1; then
|
|
# Exclude common false positives
|
|
if ! grep -iE "(sha256|md5|hash|test|example|fixture|integrity)" "$file" >/dev/null 2>&1; then
|
|
HIGH_ENTROPY_VIOLATIONS+=("$file")
|
|
fi
|
|
fi
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# Check for hardcoded paths (Unix/Windows)
|
|
if ! echo "$file" | grep -qE "(test|mock|example|\.md$|docker|Docker|\.yml$|\.yaml$|config/paths\.py$|security/path_validator\.py$)"; then
|
|
# Look for absolute paths and user home directories
|
|
if grep -E "(/home/[a-zA-Z0-9_-]+|/Users/[a-zA-Z0-9_-]+|C:\\\\Users\\\\[a-zA-Z0-9_-]+|/opt/|/var/|/etc/|/usr/local/)" "$file" >/dev/null 2>&1; then
|
|
# Exclude common false positives and Docker volume mounts
|
|
if ! grep -iE "(example|sample|placeholder|TODO|FIXME|/usr/local/bin|/etc/hosts|documentation|/etc/searxng|volumes?:|docker)" "$file" >/dev/null 2>&1; then
|
|
HARDCODED_PATH_VIOLATIONS+=("$file")
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# Check for hardcoded IP addresses
|
|
if ! echo "$file" | grep -qE "(test|mock|example|\.md$)"; then
|
|
# Look for IPv4 addresses (excluding common safe ones)
|
|
if grep -E "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" "$file" >/dev/null 2>&1; then
|
|
# Exclude localhost, documentation IPs, and common examples
|
|
if ! grep -E "\b(127\.0\.0\.1|0\.0\.0\.0|localhost|192\.168\.|10\.|172\.(1[6-9]|2[0-9]|3[0-1])\.|255\.255\.255\.|192\.0\.2\.|198\.51\.100\.|203\.0\.113\.)" "$file" >/dev/null 2>&1; then
|
|
# Additional check to exclude obvious non-IPs (version numbers, etc)
|
|
if grep -E "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" "$file" | grep -vE "(version|v[0-9]+\.|release|tag)" >/dev/null 2>&1; then
|
|
HARDCODED_IP_VIOLATIONS+=("$file")
|
|
fi
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# 7. Suspicious file type check - detect potentially dangerous file types
|
|
if [ -f "$file" ]; then
|
|
# Check if file is in the suspicious-filetypes ignore list
|
|
FILETYPE_IGNORED=false
|
|
for fpath in "${IGNORE_SUSPICIOUS_FILETYPES[@]+${IGNORE_SUSPICIOUS_FILETYPES[@]}}"; do
|
|
[ "$file" = "$fpath" ] && FILETYPE_IGNORED=true && break
|
|
done
|
|
|
|
if [ "$FILETYPE_IGNORED" = "false" ]; then
|
|
# Check for suspicious file extensions
|
|
if echo "$file" | grep -iE "\.(exe|dll|so|dylib|bin|deb|rpm|msi|dmg|pkg|app)$" >/dev/null; then
|
|
SUSPICIOUS_FILETYPE_VIOLATIONS+=("$file (executable/binary)")
|
|
elif echo "$file" | grep -iE "\.(zip|tar|gz|rar|7z|tar\.gz|tar\.bz2|tgz)$" >/dev/null; then
|
|
SUSPICIOUS_FILETYPE_VIOLATIONS+=("$file (compressed archive)")
|
|
elif echo "$file" | grep -iE "\.(log|tmp|temp|cache|bak|backup|swp|swo|DS_Store|thumbs\.db|desktop\.ini|~|\.orig|\.rej|\.patch)$" >/dev/null; then
|
|
SUSPICIOUS_FILETYPE_VIOLATIONS+=("$file (temporary/cache)")
|
|
elif echo "$file" | grep -iE "\.(png|jpg|jpeg|gif|bmp|tiff|svg|ico|webp)$" >/dev/null; then
|
|
# Images are suspicious unless in specific directories
|
|
if ! echo "$file" | grep -qE "(^docs/images/|^src/local_deep_research/web/static/favicon\.png$|^installers/.*\.ico$)"; then
|
|
SUSPICIOUS_FILETYPE_VIOLATIONS+=("$file (image file)")
|
|
fi
|
|
elif echo "$file" | grep -iE "\.(mp3|mp4|wav|avi|mov|mkv|flv|wmv|webm|m4a|ogg)$" >/dev/null; then
|
|
SUSPICIOUS_FILETYPE_VIOLATIONS+=("$file (media file)")
|
|
elif echo "$file" | grep -iE "\.(csv|xlsx|xls|doc|docx|pdf|ppt|pptx)$" >/dev/null; then
|
|
# Documents are suspicious unless in docs directory
|
|
if ! echo "$file" | grep -qE "docs/"; then
|
|
SUSPICIOUS_FILETYPE_VIOLATIONS+=("$file (document file)")
|
|
fi
|
|
elif echo "$file" | grep -iE "\.(db|sqlite|sqlite3)$" >/dev/null; then
|
|
SUSPICIOUS_FILETYPE_VIOLATIONS+=("$file (database file)")
|
|
elif echo "$file" | grep -iE "node_modules/|__pycache__/|\.pyc$|\.pyo$|\.egg-info/|dist/|build/|\.cache/" >/dev/null; then
|
|
SUSPICIOUS_FILETYPE_VIOLATIONS+=("$file (build artifact/cache)")
|
|
fi
|
|
fi
|
|
fi
|
|
fi
|
|
done <<< "$CHANGED_FILES"
|
|
|
|
echo ""
|
|
echo "✓ Checked $FILES_CHECKED files"
|
|
echo ""
|
|
|
|
# Report all violations with detailed explanations
|
|
echo "📊 Security scan completed. Analyzing results..."
|
|
echo "📋 Summary of findings:"
|
|
echo " - File type violations: ${#WHITELIST_VIOLATIONS[@]}"
|
|
echo " - Large files: ${#LARGE_FILES[@]}"
|
|
echo " - Binary files: ${#BINARY_FILES[@]}"
|
|
echo " - Suspicious filenames: ${#SUSPICIOUS_FILES[@]}"
|
|
echo " - Research data leaks: ${#RESEARCH_DATA_VIOLATIONS[@]}"
|
|
echo " - Hardcoded Flask secrets: ${#FLASK_SECRET_VIOLATIONS[@]}"
|
|
echo " - Environment files: ${#ENV_FILE_VIOLATIONS[@]}"
|
|
echo " - High-entropy strings: ${#HIGH_ENTROPY_VIOLATIONS[@]}"
|
|
echo " - Hardcoded paths: ${#HARDCODED_PATH_VIOLATIONS[@]}"
|
|
echo " - Hardcoded IPs: ${#HARDCODED_IP_VIOLATIONS[@]}"
|
|
echo " - Suspicious file types: ${#SUSPICIOUS_FILETYPE_VIOLATIONS[@]}"
|
|
|
|
TOTAL_VIOLATIONS=0
|
|
|
|
if [ ${#WHITELIST_VIOLATIONS[@]} -gt 0 ]; then
|
|
echo ""
|
|
echo "❌ WHITELIST VIOLATIONS - File types not allowed in repository:"
|
|
echo " These files don't match any pattern in .file-whitelist.txt."
|
|
echo " Binary files (images, audio, etc.) bloat the repo and should NOT be committed."
|
|
echo " Only a small set of explicitly listed binary files is allowed — store others externally."
|
|
echo " If this is a legitimate text/config file, add it to .file-whitelist.txt (requires maintainer approval)."
|
|
echo ""
|
|
for violation in "${WHITELIST_VIOLATIONS[@]}"; do
|
|
echo " 🚫 $violation"
|
|
|
|
# Show file type and extension
|
|
FILE_EXT="${violation##*.}"
|
|
if [ -f "$violation" ]; then
|
|
FILE_TYPE=$(file -b "$violation" 2>/dev/null || echo "unknown")
|
|
echo " → File extension: .$FILE_EXT"
|
|
echo " → File type: $FILE_TYPE"
|
|
echo " → First few lines:"
|
|
head -3 "$violation" 2>/dev/null | while read -r line; do
|
|
echo " $line"
|
|
done
|
|
fi
|
|
|
|
echo " → Issue: File extension/type not in .file-whitelist.txt"
|
|
echo " → Fix: For text/config files, add pattern to .file-whitelist.txt"
|
|
echo " → Note: Binary files should NOT be added to the repo — store them externally"
|
|
echo ""
|
|
done
|
|
TOTAL_VIOLATIONS=$((TOTAL_VIOLATIONS + ${#WHITELIST_VIOLATIONS[@]}))
|
|
fi
|
|
|
|
if [ ${#LARGE_FILES[@]} -gt 0 ]; then
|
|
echo ""
|
|
echo "❌ LARGE FILES (>1MB) - Files too big for repository:"
|
|
echo " Large files should typically be stored externally or compressed."
|
|
echo ""
|
|
for violation in "${LARGE_FILES[@]}"; do
|
|
echo " 📏 $violation"
|
|
echo " → Issue: File size exceeds 1MB limit"
|
|
echo " → Fix: Use Git LFS, external storage, or compress the file"
|
|
echo ""
|
|
done
|
|
TOTAL_VIOLATIONS=$((TOTAL_VIOLATIONS + ${#LARGE_FILES[@]}))
|
|
fi
|
|
|
|
if [ ${#BINARY_FILES[@]} -gt 0 ]; then
|
|
echo ""
|
|
echo "⚠️ BINARY FILES DETECTED - Review these carefully:"
|
|
echo " Binary files may contain sensitive data and can't be easily reviewed."
|
|
echo ""
|
|
for violation in "${BINARY_FILES[@]}"; do
|
|
echo " 🔒 $violation"
|
|
echo " → Issue: Binary file detected (contents not reviewable)"
|
|
echo " → Action: Verify this file doesn't contain sensitive data"
|
|
echo ""
|
|
done
|
|
fi
|
|
|
|
if [ ${#SUSPICIOUS_FILES[@]} -gt 0 ]; then
|
|
echo ""
|
|
echo "❌ SUSPICIOUS FILENAMES - Files with security-sensitive names:"
|
|
echo " These filenames contain words that often indicate sensitive files."
|
|
echo ""
|
|
for violation in "${SUSPICIOUS_FILES[@]}"; do
|
|
echo " 🚨 $violation"
|
|
|
|
# Show which keyword triggered the detection
|
|
if echo "$violation" | grep -qi "secret"; then
|
|
echo " → Triggered by: 'secret' in filename"
|
|
elif echo "$violation" | grep -qi "password"; then
|
|
echo " → Triggered by: 'password' in filename"
|
|
elif echo "$violation" | grep -qi "token"; then
|
|
echo " → Triggered by: 'token' in filename"
|
|
elif echo "$violation" | grep -qi "api"; then
|
|
echo " → Triggered by: 'api' in filename"
|
|
elif echo "$violation" | grep -qi "key"; then
|
|
echo " → Triggered by: 'key' in filename"
|
|
fi
|
|
|
|
# Show file content preview if it exists
|
|
if [ -f "$violation" ]; then
|
|
FILE_TYPE=$(file -b "$violation" 2>/dev/null || echo "unknown")
|
|
FILE_SIZE=$(stat -c%s "$violation" 2>/dev/null || echo "unknown")
|
|
echo " → File info: $FILE_TYPE (${FILE_SIZE} bytes)"
|
|
echo " → Content preview:"
|
|
head -3 "$violation" 2>/dev/null | while read -r line; do
|
|
echo " $line"
|
|
done
|
|
fi
|
|
|
|
echo " → Issue: Filename contains suspicious keywords (secret/password/token/key)"
|
|
echo " → Fix: Rename file or add to SAFE_FILENAME_PATTERNS whitelist"
|
|
echo ""
|
|
done
|
|
TOTAL_VIOLATIONS=$((TOTAL_VIOLATIONS + ${#SUSPICIOUS_FILES[@]}))
|
|
fi
|
|
|
|
# LDR-specific violation reports
|
|
if [ ${#RESEARCH_DATA_VIOLATIONS[@]} -gt 0 ]; then
|
|
echo ""
|
|
echo "❌ RESEARCH DATA LEAKAGE - Hardcoded research session data found:"
|
|
echo " Research IDs and session data should never be hardcoded in production code."
|
|
echo ""
|
|
for violation in "${RESEARCH_DATA_VIOLATIONS[@]}"; do
|
|
echo " 📊 $violation"
|
|
|
|
# Show the specific lines with research data
|
|
echo " → Found hardcoded research data:"
|
|
grep -n -E "(research_id|session_id|query_id).*=.*[\"'][0-9a-f]{8,}[\"']" "$violation" 2>/dev/null | head -3 | while read -r line; do
|
|
echo " $line"
|
|
done
|
|
|
|
echo " → Issue: Hardcoded research/session IDs in non-test file"
|
|
echo " → Fix: Use environment variables or configuration files"
|
|
echo ""
|
|
done
|
|
TOTAL_VIOLATIONS=$((TOTAL_VIOLATIONS + ${#RESEARCH_DATA_VIOLATIONS[@]}))
|
|
fi
|
|
|
|
if [ ${#FLASK_SECRET_VIOLATIONS[@]} -gt 0 ]; then
|
|
echo ""
|
|
echo "❌ FLASK SECRET KEY - Hardcoded Flask secret keys found:"
|
|
echo " Flask secret keys must never be hardcoded for security reasons."
|
|
echo ""
|
|
for violation in "${FLASK_SECRET_VIOLATIONS[@]}"; do
|
|
echo " 🔐 $violation"
|
|
|
|
# Show the specific lines with secret keys
|
|
echo " → Found hardcoded Flask secret key:"
|
|
grep -n -E "SECRET_KEY.*=.*[\"'][^\"']{16,}[\"']" "$violation" 2>/dev/null | head -3 | while read -r line; do
|
|
echo " $line"
|
|
done
|
|
|
|
echo " → Issue: Hardcoded Flask SECRET_KEY"
|
|
echo " → Fix: Use os.environ or load from secure config file"
|
|
echo ""
|
|
done
|
|
TOTAL_VIOLATIONS=$((TOTAL_VIOLATIONS + ${#FLASK_SECRET_VIOLATIONS[@]}))
|
|
fi
|
|
|
|
if [ ${#ENV_FILE_VIOLATIONS[@]} -gt 0 ]; then
|
|
echo ""
|
|
echo "❌ ENVIRONMENT FILES - .env files detected:"
|
|
echo " Environment files contain sensitive configuration and should never be committed."
|
|
echo ""
|
|
for violation in "${ENV_FILE_VIOLATIONS[@]}"; do
|
|
echo " 🌍 $violation"
|
|
echo " → Issue: Environment file in repository"
|
|
echo " → Fix: Add to .gitignore and use .env.example instead"
|
|
echo ""
|
|
done
|
|
TOTAL_VIOLATIONS=$((TOTAL_VIOLATIONS + ${#ENV_FILE_VIOLATIONS[@]}))
|
|
fi
|
|
|
|
if [ ${#HIGH_ENTROPY_VIOLATIONS[@]} -gt 0 ]; then
|
|
echo ""
|
|
echo "❌ HIGH ENTROPY STRINGS - Potential secrets or keys detected:"
|
|
echo " Long random strings may be API keys, tokens, or other secrets."
|
|
echo ""
|
|
for violation in "${HIGH_ENTROPY_VIOLATIONS[@]}"; do
|
|
echo " 🎲 $violation"
|
|
|
|
# Show sample of high entropy strings
|
|
echo " → Found high-entropy strings:"
|
|
grep -n -E "[a-zA-Z0-9+/]{40,}={0,2}|[a-f0-9]{40,}" "$violation" 2>/dev/null | head -3 | while read -r line; do
|
|
# Truncate long lines for readability
|
|
echo " ${line:0:120}..."
|
|
done
|
|
|
|
echo " → Issue: High-entropy strings that could be secrets"
|
|
echo " → Fix: Review and move to environment variables if sensitive"
|
|
echo ""
|
|
done
|
|
TOTAL_VIOLATIONS=$((TOTAL_VIOLATIONS + ${#HIGH_ENTROPY_VIOLATIONS[@]}))
|
|
fi
|
|
|
|
if [ ${#HARDCODED_PATH_VIOLATIONS[@]} -gt 0 ]; then
|
|
echo ""
|
|
echo "❌ HARDCODED PATHS - System-specific paths detected:"
|
|
echo " Absolute paths can expose system structure and break portability."
|
|
echo ""
|
|
for violation in "${HARDCODED_PATH_VIOLATIONS[@]}"; do
|
|
echo " 📁 $violation"
|
|
|
|
# Show the specific hardcoded paths
|
|
echo " → Found hardcoded paths:"
|
|
grep -n -E "(/home/[a-zA-Z0-9_-]+|/Users/[a-zA-Z0-9_-]+|C:\\\\Users\\\\[a-zA-Z0-9_-]+|/opt/|/var/|/etc/|/usr/local/)" "$violation" 2>/dev/null | head -5 | while read -r line; do
|
|
echo " $line"
|
|
done
|
|
|
|
echo " → Issue: Hardcoded absolute paths reduce portability"
|
|
echo " → Fix: Use relative paths, environment variables, or config files"
|
|
echo ""
|
|
done
|
|
TOTAL_VIOLATIONS=$((TOTAL_VIOLATIONS + ${#HARDCODED_PATH_VIOLATIONS[@]}))
|
|
fi
|
|
|
|
if [ ${#HARDCODED_IP_VIOLATIONS[@]} -gt 0 ]; then
|
|
echo ""
|
|
echo "❌ HARDCODED IP ADDRESSES - External IP addresses detected:"
|
|
echo " Hardcoded IPs can expose infrastructure and cause connectivity issues."
|
|
echo ""
|
|
for violation in "${HARDCODED_IP_VIOLATIONS[@]}"; do
|
|
echo " 🌐 $violation"
|
|
|
|
# Show the specific IP addresses
|
|
echo " → Found hardcoded IP addresses:"
|
|
grep -n -E "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" "$violation" 2>/dev/null | grep -v -E "(127\.0\.0\.1|0\.0\.0\.0|localhost|192\.168\.|10\.|172\.(1[6-9]|2[0-9]|3[0-1])\.|255\.255\.255\.|192\.0\.2\.|198\.51\.100\.|203\.0\.113\.)" | head -5 | while read -r line; do
|
|
echo " $line"
|
|
done
|
|
|
|
echo " → Issue: Hardcoded IP addresses (non-private/localhost)"
|
|
echo " → Fix: Use DNS names, environment variables, or config files"
|
|
echo ""
|
|
done
|
|
TOTAL_VIOLATIONS=$((TOTAL_VIOLATIONS + ${#HARDCODED_IP_VIOLATIONS[@]}))
|
|
fi
|
|
|
|
if [ ${#SUSPICIOUS_FILETYPE_VIOLATIONS[@]} -gt 0 ]; then
|
|
echo ""
|
|
echo "❌ SUSPICIOUS FILE TYPES - Potentially dangerous file types detected:"
|
|
echo " These file types are commonly used for malware, data leaks, or bloat the repository."
|
|
echo ""
|
|
for violation in "${SUSPICIOUS_FILETYPE_VIOLATIONS[@]}"; do
|
|
echo " 🚨 $violation"
|
|
|
|
FILE_PATH="${violation%% (*}"
|
|
FILE_CATEGORY="${violation##*\\(}"
|
|
FILE_CATEGORY="${FILE_CATEGORY%\\)}"
|
|
|
|
# Provide specific guidance based on file category
|
|
case "$FILE_CATEGORY" in
|
|
"executable/binary")
|
|
echo " → Issue: Executable/binary files can contain malware"
|
|
echo " → Fix: Remove executable files, use package managers instead"
|
|
;;
|
|
"compressed archive")
|
|
echo " → Issue: Compressed archives hide their contents from review"
|
|
echo " → Fix: Extract contents and commit individual files instead"
|
|
;;
|
|
"temporary/cache")
|
|
echo " → Issue: Temporary/cache files should not be committed"
|
|
echo " → Fix: Add to .gitignore and remove from repository"
|
|
;;
|
|
"image file")
|
|
echo " → Issue: Binary image files bloat the repo and should NOT be committed"
|
|
echo " → Fix: Store images externally. Only a few explicitly listed images in docs/images/ are allowed"
|
|
;;
|
|
"media file")
|
|
echo " → Issue: Media files are large and rarely needed in code repos"
|
|
echo " → Fix: Use external hosting or remove if unnecessary"
|
|
;;
|
|
"document file")
|
|
echo " → Issue: Office documents should be in docs/ directory if needed"
|
|
echo " → Fix: Move to docs/ directory or convert to markdown"
|
|
;;
|
|
"database file")
|
|
echo " → Issue: Database files contain data that shouldn't be in source control"
|
|
echo " → Fix: Add to .gitignore and use migrations/seeds instead"
|
|
;;
|
|
"build artifact/cache")
|
|
echo " → Issue: Build artifacts and cache files bloat the repository"
|
|
echo " → Fix: Add to .gitignore and remove from repository"
|
|
;;
|
|
esac
|
|
|
|
# Show file info if available
|
|
if [ -f "$FILE_PATH" ]; then
|
|
FILE_SIZE=$(stat -c%s "$FILE_PATH" 2>/dev/null || echo "unknown")
|
|
if [ "$FILE_SIZE" != "unknown" ]; then
|
|
READABLE_SIZE=$(echo "$FILE_SIZE" | awk '{if($1>=1048576) printf "%.1fMB", $1/1048576; else if($1>=1024) printf "%.1fKB", $1/1024; else printf "%dB", $1}')
|
|
echo " → File size: $READABLE_SIZE"
|
|
fi
|
|
fi
|
|
echo ""
|
|
done
|
|
TOTAL_VIOLATIONS=$((TOTAL_VIOLATIONS + ${#SUSPICIOUS_FILETYPE_VIOLATIONS[@]}))
|
|
fi
|
|
|
|
# Final result
|
|
if [ $TOTAL_VIOLATIONS -eq 0 ]; then
|
|
echo ""
|
|
echo "✅ All security checks passed!"
|
|
exit 0
|
|
else
|
|
echo ""
|
|
echo "💡 To fix these issues:"
|
|
echo " - For text/config files: add pattern to .file-whitelist.txt (requires maintainer approval)"
|
|
echo " - For binary files (images, audio, video, archives): do NOT add to the repo"
|
|
echo " Binary files permanently bloat git history. Store them externally instead."
|
|
echo " Only a small set of explicitly listed binary files is permitted."
|
|
echo " - Use environment variables for secrets"
|
|
echo " - Never hardcode research data or session IDs"
|
|
echo " - Use .env.example files instead of .env"
|
|
echo " - Replace absolute paths with relative paths or configs"
|
|
echo " - Use DNS names instead of hardcoded IP addresses"
|
|
echo ""
|
|
echo "⚠️ SECURITY REMINDER: This is a public repository!"
|
|
echo " Never commit sensitive data, API keys, or personal information."
|
|
exit 1
|
|
fi
|