diff --git a/CHANGELOG.md b/CHANGELOG.md index 0aa0ac8..715dc36 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,47 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.2.1] - 2026-02-03 + +### Added + +- **Enhanced project type detection for non-WordPress codebases:** + - Detects frameworks from `package.json` dependencies: `nodejs`, `react`, `nextjs`, `vue`, `nuxt`, `express`, `typescript` + - Comma-separated output when multiple frameworks detected (e.g., `[nodejs, react, nextjs]`) + - Extracts project name, version, description, and author from `package.json` + - Falls back to file-based detection: `javascript` (JS/TS files), `php` (PHP files), `php, javascript` (mixed) + - WordPress plugin/theme detection unchanged and takes precedence + +### Fixed + +- **PHP superglobal rules now respect PHP-only scope in JS/Node scans:** + - Updated `dist/bin/check-performance.sh` so Direct Superglobal Manipulation (`spo-002-superglobals`) and Unsanitized Superglobal Read rules explicitly restrict grep to `*.php` files. + - Prevents PHP-specific security checks from scanning documentation files (e.g., `.md`) and non-PHP assets when running WPCC against JS/Node/React projects. + - Resolves false positives where Markdown docs containing PHP examples triggered superglobal findings in JS-only repositories. + +### Tested + +- ✅ PHP file discovery and caching verified (lines 3147-3178) +- ✅ PHP security patterns have `--include=*.php` guards (lines 3368, 3536) +- ✅ `cached_grep` fallback handles JS-only projects (lines 3271-3280) +- ✅ `unsanitized-superglobal-read.php` fixture: detects violations correctly +- ✅ `wpdb-no-prepare.php` fixture: detects SQL injection risks +- ✅ JS-only directory (`headless/`): runs without crashing, no false positives +- ✅ Backwards compatibility confirmed: existing PHP scanning unchanged +- ✅ Type detection: `nodejs` from package.json +- ✅ Type detection: `nodejs, react, nextjs` from Next.js project +- ✅ Type detection: `nodejs, typescript, vue, nuxt` from Nuxt project +- ✅ Type detection: `php, javascript` from mixed fixtures directory + +## [2.2.0] - 2026-02-03 + +### Added + +- **JS/Node-only project support:** Relaxed the PHP file gate so WP Code Check can analyze pure JavaScript/TypeScript and Node/React codebases. + - When no PHP files are found but JS/TS files are present, the scanner now skips PHP-only checks gracefully and runs headless/Node.js/JS pattern sets instead. + - Grep helpers fall back to recursive search over the original paths when the PHP file cache is unavailable, preserving performance optimizations for PHP projects while enabling non-WordPress scans. + - JSON and HTML report generation remain fully supported for these non-WordPress projects. + ## [2.1.0] - 2026-01-28 ### Added diff --git a/dist/bin/check-performance.sh b/dist/bin/check-performance.sh index 90fa22a..37df902 100755 --- a/dist/bin/check-performance.sh +++ b/dist/bin/check-performance.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # # WP Code Check by Hypercart - Performance Analysis Script -# Version: 2.0.15 +# Version: 2.2.0 # # Fast, zero-dependency WordPress performance analyzer # Catches critical issues before they crash your site @@ -81,7 +81,7 @@ source "$REPO_ROOT/lib/pattern-loader.sh" # This is the ONLY place the version number should be defined. # All other references (logs, JSON, banners) use this variable. # Update this ONE line when bumping versions - never hardcode elsewhere. -SCRIPT_VERSION="2.1.0" +SCRIPT_VERSION="2.2.1" # Get the start/end line range for the enclosing function/method. # @@ -1024,8 +1024,82 @@ detect_project_info() { project_type="fixture" project_name=$(basename "$scan_path") else - # Generic project + # Generic project - detect from package.json or file types project_name=$(basename "$scan_path") + + # Check for package.json (Node.js/JS projects) + local pkg_json="" + if [ -f "$scan_path/package.json" ]; then + pkg_json="$scan_path/package.json" + elif [ -f "$(dirname "$scan_path")/package.json" ]; then + pkg_json="$(dirname "$scan_path")/package.json" + fi + + if [ -n "$pkg_json" ]; then + # Build comma-separated type list from detected frameworks + local detected_types="" + + # Base: it's a Node.js project + detected_types="nodejs" + + # Detect TypeScript + if grep -qE '"typescript"|"ts-node"' "$pkg_json" 2>/dev/null; then + detected_types="$detected_types, typescript" + fi + + # Detect React + if grep -qE '"react"[[:space:]]*:' "$pkg_json" 2>/dev/null; then + detected_types="$detected_types, react" + fi + + # Detect Next.js (after React, as Next includes React) + if grep -qE '"next"[[:space:]]*:' "$pkg_json" 2>/dev/null; then + detected_types="$detected_types, nextjs" + fi + + # Detect Vue.js + if grep -qE '"vue"[[:space:]]*:' "$pkg_json" 2>/dev/null; then + detected_types="$detected_types, vue" + fi + + # Detect Nuxt (Vue's Next.js equivalent) + if grep -qE '"nuxt"[[:space:]]*:' "$pkg_json" 2>/dev/null; then + detected_types="$detected_types, nuxt" + fi + + # Detect Express.js + if grep -qE '"express"[[:space:]]*:' "$pkg_json" 2>/dev/null; then + detected_types="$detected_types, express" + fi + + project_type="$detected_types" + + # Extract name/version from package.json if not already set + if [ "$project_name" = "Unknown" ] || [ -z "$project_name" ]; then + project_name=$(grep -o '"name"[[:space:]]*:[[:space:]]*"[^"]*"' "$pkg_json" 2>/dev/null | head -1 | cut -d'"' -f4) + fi + if [ -z "$project_version" ]; then + project_version=$(grep -o '"version"[[:space:]]*:[[:space:]]*"[^"]*"' "$pkg_json" 2>/dev/null | head -1 | cut -d'"' -f4) + fi + if [ -z "$project_description" ]; then + project_description=$(grep -o '"description"[[:space:]]*:[[:space:]]*"[^"]*"' "$pkg_json" 2>/dev/null | head -1 | cut -d'"' -f4) + fi + if [ -z "$project_author" ]; then + project_author=$(grep -o '"author"[[:space:]]*:[[:space:]]*"[^"]*"' "$pkg_json" 2>/dev/null | head -1 | cut -d'"' -f4) + fi + elif [ -d "$scan_path" ]; then + # No package.json - detect by file presence + local has_js=$(find "$scan_path" -maxdepth 2 \( -name "*.js" -o -name "*.ts" -o -name "*.jsx" -o -name "*.tsx" \) -type f 2>/dev/null | head -1) + local has_php=$(find "$scan_path" -maxdepth 2 -name "*.php" -type f 2>/dev/null | head -1) + + if [ -n "$has_js" ] && [ -n "$has_php" ]; then + project_type="php, javascript" + elif [ -n "$has_js" ]; then + project_type="javascript" + elif [ -n "$has_php" ]; then + project_type="php" + fi + fi fi fi @@ -1194,6 +1268,8 @@ if [ "$ENABLE_LOGGING" = true ]; then theme) type_display_log="WordPress Theme" ;; fixture) type_display_log="Fixture Test" ;; unknown) type_display_log="Unknown" ;; + # New types pass through as-is (already descriptive, e.g., "nodejs, react, nextjs") + nodejs*|javascript*|php*|react*|vue*|typescript*) type_display_log="$PROJECT_TYPE_LOG" ;; esac echo "Type: $type_display_log" if [ -n "$PROJECT_AUTHOR_LOG" ]; then @@ -1633,6 +1709,8 @@ generate_html_report() { theme) type_display="WordPress Theme" ;; fixture) type_display="Fixture Test" ;; unknown) type_display="Unknown" ;; + # New types pass through as-is (already descriptive, e.g., "nodejs, react, nextjs") + nodejs*|javascript*|php*|react*|vue*|typescript*) type_display="$project_type" ;; esac project_info_html="