Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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).

## [1.1.2] - 2026-01-09

### Added
- **New Pattern: HTML-Escaping in JSON Response URL Fields** (`wp-json-html-escape`) - **HEURISTIC**
- **Category:** Reliability / Correctness
- **Severity:** MEDIUM (warning)
- **Type:** Heuristic (needs review)
- **Description:** Detects HTML escaping functions (`esc_url`, `esc_attr`, `esc_html`) used in JSON response fields with URL-like names, which can cause double-encoding issues
- **Problem:** Using `esc_url()` in JSON responses encodes `&` → `&`, breaking redirects in JavaScript
- **Detection Strategy:** Two-step approach:
1. Find files with JSON response functions (`wp_send_json_*`, `WP_REST_Response`, `wp_json_encode`)
2. Check for `esc_url/esc_attr/esc_html` in array keys matching URL patterns (`url`, `redirect`, `link`, `href`, `view_url`, `redirect_url`, `edit_url`, `delete_url`, `ajax_url`, `api_url`, `endpoint`)
- **Why Heuristic:**
- Sometimes developers intentionally send HTML fragments in JSON (e.g., `html_content` field)
- Escaping may be correct for non-URL fields (e.g., `message` field)
- Context matters - pattern flags suspicious cases for review
- **Remediation:**
- Remove HTML escaping from JSON URL fields
- Use raw URLs in JSON responses
- Escape only when rendering into HTML context in JavaScript
- **Example:**
```php
// ❌ Bad - Double-encoding
wp_send_json_success(array(
'redirect_url' => esc_url($url) // & becomes &
));

// ✅ Good - Raw URL
wp_send_json_success(array(
'redirect_url' => $url // Escape in JS when needed
));
```
- **Files Added:**
- `dist/bin/patterns/wp-json-html-escape.json` - Pattern definition with heuristic flag
- `dist/bin/fixtures/wp-json-html-escape.php` - Test fixture with 11 test cases (8 true positives, 3 edge cases)
- **Pattern Library:** Now 29 total patterns (18 PHP, 6 Headless, 4 Node.js, 1 JS)
- **Heuristic Patterns:** Now 10 total (was 9)
- **Impact:** Helps prevent hard-to-debug redirect failures and double-encoding issues in AJAX/REST API responses
- **Test Status:** ✅ Tested with fixture - detected 11/11 expected cases (8 true positives + 3 edge cases)
- **Main Scanner Integration:** Integrated at lines 4778-4844 (after Smart Coupons check, before Transient check)

## [1.1.1] - 2026-01-08

### Added
Expand Down
28 changes: 21 additions & 7 deletions dist/PATTERN-LIBRARY.json
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
{
"version": "1.0.0",
"generated": "2026-01-08T20:45:21Z",
"generated": "2026-01-09T20:37:56Z",
"summary": {
"total_patterns": 28,
"enabled": 28,
"total_patterns": 29,
"enabled": 29,
"disabled": 0,
"by_severity": {
"CRITICAL": 9,
"HIGH": 10,
"MEDIUM": 6,
"MEDIUM": 7,
"LOW": 3
},
"by_category": {
"performance": 9,"duplication": 5,"reliability": 4,"security": 8
"performance": 9,"duplication": 5,"reliability": 5,"security": 8
},
"by_pattern_type": {
"php": 17,
"php": 18,
"headless": 6,
"nodejs": 4,
"javascript": 1
},
"mitigation_detection_enabled": 4,
"heuristic_patterns": 9,
"heuristic_patterns": 10,
"definitive_patterns": 19
},
"patterns": [
Expand Down Expand Up @@ -375,6 +375,20 @@
"heuristic": false,
"file": "wc-smart-coupons-thankyou-perf.json"
},
{
"id": "wp-json-html-escape",
"version": "",
"enabled": true,
"category": "reliability",
"severity": "MEDIUM",
"title": "HTML-escaping in JSON response URL fields",
"description": "Detects HTML escaping functions (esc_url, esc_attr, esc_html) used in JSON response fields with URL-like names. This can cause double-encoding issues where & becomes & breaking redirects in JavaScript.",
"detection_type": "",
"pattern_type": "php",
"mitigation_detection": false,
"heuristic": true,
"file": "wp-json-html-escape.json"
},
{
"id": "wp-query-unbounded",
"version": "1.0.0",
Expand Down
37 changes: 19 additions & 18 deletions dist/PATTERN-LIBRARY.md
Original file line number Diff line number Diff line change
@@ -1,43 +1,43 @@
# Pattern Library Registry

**Auto-generated by Pattern Library Manager**
**Last Updated:** 2026-01-08 20:45:21 UTC
**Last Updated:** 2026-01-09 20:37:56 UTC

---

## 📊 Summary Statistics

### Total Patterns
- **Total:** 28 patterns
- **Enabled:** 28 patterns
- **Total:** 29 patterns
- **Enabled:** 29 patterns
- **Disabled:** 0 patterns

### By Severity
| Severity | Count | Percentage |
|----------|-------|------------|
| CRITICAL | 9 | 32.1% |
| HIGH | 10 | 35.7% |
| MEDIUM | 6 | 21.4% |
| LOW | 3 | 10.7% |
| CRITICAL | 9 | 31.0% |
| HIGH | 10 | 34.5% |
| MEDIUM | 7 | 24.1% |
| LOW | 3 | 10.3% |

### By Type
| Type | Count | Percentage |
|------|-------|------------|
| Definitive | 19 | 67.9% |
| Heuristic | 9 | 32.1% |
| Definitive | 19 | 65.5% |
| Heuristic | 10 | 34.5% |

### Advanced Features
- **Mitigation Detection Enabled:** 4 patterns (14.3%)
- **Mitigation Detection Enabled:** 4 patterns (13.8%)
- **False Positive Reduction:** 60-70% on mitigated patterns

### By Category
- **performance:** 9 patterns
- **duplication:** 5 patterns
- **reliability:** 4 patterns
- **reliability:** 5 patterns
- **security:** 8 patterns

### By Pattern Type
- **PHP/WordPress:** 17 patterns
- **PHP/WordPress:** 18 patterns
- **Headless WordPress:** 6 patterns
- **Node.js/Server-Side JS:** 4 patterns
- **Client-Side JavaScript:** 1 patterns
Expand Down Expand Up @@ -77,6 +77,7 @@
- **headless-hardcoded-wordpress-url** 🔍 - Hardcoded WordPress API URL
- **headless-nextjs-missing-revalidate** 🔍 - Next.js getStaticProps without revalidate (stale WordPress data)
- **limit-multiplier-from-count** 🔍 - Query limit multiplier derived from count()
- **wp-json-html-escape** 🔍 - HTML-escaping in JSON response URL fields

### LOW Severity Patterns
- **array-merge-in-loop** 🔍 - array_merge() inside loops (potential OOM)
Expand All @@ -96,26 +97,26 @@

### Key Selling Points

1. **Comprehensive Coverage:** 28 detection patterns across 4 categories
2. **Multi-Platform Support:** PHP/WordPress (17), Headless WordPress (6), Node.js (4), JavaScript (1)
1. **Comprehensive Coverage:** 29 detection patterns across 4 categories
2. **Multi-Platform Support:** PHP/WordPress (18), Headless WordPress (6), Node.js (4), JavaScript (1)
3. **Enterprise-Grade Accuracy:** 4 patterns with AI-powered mitigation detection (60-70% false positive reduction)
4. **Severity-Based Prioritization:** 9 CRITICAL + 10 HIGH severity patterns catch the most dangerous issues
5. **Intelligent Analysis:** 19 definitive patterns + 9 heuristic patterns for comprehensive code review
5. **Intelligent Analysis:** 19 definitive patterns + 10 heuristic patterns for comprehensive code review

### One-Liner Stats

> **28 detection patterns** | **4 with AI mitigation** | **60-70% fewer false positives** | **Multi-platform: PHP, Headless, Node.js, JS**
> **29 detection patterns** | **4 with AI mitigation** | **60-70% fewer false positives** | **Multi-platform: PHP, Headless, Node.js, JS**

### Feature Highlights

- ✅ **9 CRITICAL** OOM and security patterns
- ✅ **10 HIGH** performance and security patterns
- ✅ **4 patterns** with context-aware severity adjustment
- ✅ **9 heuristic** patterns for code quality insights
- ✅ **10 heuristic** patterns for code quality insights
- ✅ **Multi-platform:** WordPress, Headless, Node.js, JavaScript

---

**Generated:** 2026-01-08 20:45:21 UTC
**Generated:** 2026-01-09 20:37:56 UTC
**Version:** 1.0.0
**Tool:** Pattern Library Manager
67 changes: 66 additions & 1 deletion dist/bin/check-performance.sh
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,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="1.1.0"
SCRIPT_VERSION="1.1.2"

# Get the start/end line range for the enclosing function/method.
#
Expand Down Expand Up @@ -4775,6 +4775,71 @@ else
fi
text_echo ""

# ============================================================================
# HTML-Escaping in JSON Response URL Fields (Heuristic)
# ============================================================================
# Pattern: wp-json-html-escape
# Detects HTML escaping functions (esc_url, esc_attr, esc_html) used in JSON
# response fields with URL-like names. This can cause double-encoding where
# & becomes & breaking redirects in JavaScript.
# This is a HEURISTIC pattern - may flag intentional HTML fragments in JSON.
# ============================================================================

JSON_HTML_ESCAPE_SEVERITY=$(get_severity "wp-json-html-escape" "MEDIUM")
JSON_HTML_ESCAPE_COLOR="${YELLOW}"

text_echo "${BLUE}▸ HTML-escaping in JSON response URL fields (heuristic) ${JSON_HTML_ESCAPE_COLOR}[$JSON_HTML_ESCAPE_SEVERITY]${NC}"

# Step 1: Find files with JSON response functions
JSON_RESPONSE_FILES=$(grep -rlE \
'wp_send_json|WP_REST_Response|wp_json_encode' \
$EXCLUDE_ARGS --include='*.php' "$PATHS" 2>/dev/null || true)

JSON_HTML_ESCAPE_ISSUES=""
JSON_HTML_ESCAPE_FINDING_COUNT=0

if [ -n "$JSON_RESPONSE_FILES" ]; then
# Step 2: Check for esc_* functions in URL-like keys
while IFS= read -r file; do
[ -z "$file" ] && continue

# Look for patterns like: 'redirect_url' => esc_url($url)
# Match URL-like keys with HTML escaping functions
ESCAPE_MATCHES=$(grep -nE \
"('|\")?(url|redirect|link|href|view_url|redirect_url|edit_url|delete_url|ajax_url|api_url|endpoint)('|\")?\s*(=>|:)\s*esc_(url|attr|html)\(" \
"$file" 2>/dev/null || true)

if [ -n "$ESCAPE_MATCHES" ]; then
while IFS= read -r match; do
[ -z "$match" ] && continue

line_num=$(echo "$match" | cut -d: -f1)
code=$(echo "$match" | cut -d: -f2-)

if ! should_suppress_finding "wp-json-html-escape" "$file"; then
JSON_HTML_ESCAPE_ISSUES="${JSON_HTML_ESCAPE_ISSUES}${file}:${line_num}:${code}"$'\n'
add_json_finding "wp-json-html-escape" "warning" "$JSON_HTML_ESCAPE_SEVERITY" "$file" "$line_num" "Potential HTML-escaping in JSON response. esc_url() encodes & → & which can break redirects in JS. Prefer raw URL in JSON; escape when rendering into HTML." "$code"
((JSON_HTML_ESCAPE_FINDING_COUNT++)) || true
fi
done <<< "$ESCAPE_MATCHES"
fi
done <<< "$JSON_RESPONSE_FILES"
fi

if [ "$JSON_HTML_ESCAPE_FINDING_COUNT" -gt 0 ]; then
text_echo "${JSON_HTML_ESCAPE_COLOR} ⚠ NEEDS REVIEW - HTML-escaping in JSON URL fields (heuristic):${NC}"
((WARNINGS++))
if [ "$OUTPUT_FORMAT" = "text" ]; then
echo "$JSON_HTML_ESCAPE_ISSUES" | head -5
text_echo "${YELLOW} 💡 Fix: Remove esc_url/esc_attr/esc_html from JSON URL fields. Use raw URLs; escape in JS when rendering to HTML.${NC}"
fi
add_json_check "HTML-escaping in JSON response URL fields (heuristic)" "$JSON_HTML_ESCAPE_SEVERITY" "failed" "$JSON_HTML_ESCAPE_FINDING_COUNT"
else
text_echo "${GREEN} ✓ Passed${NC}"
add_json_check "HTML-escaping in JSON response URL fields (heuristic)" "$JSON_HTML_ESCAPE_SEVERITY" "passed" 0
fi
text_echo ""

# Transient abuse check - transients without expiration
TRANSIENT_SEVERITY=$(get_severity "transient-no-expiration" "MEDIUM")
TRANSIENT_COLOR="${YELLOW}"
Expand Down
Loading
Loading