# HVAC Community Events Security Remediation Plan
## Executive Summary
This document outlines a comprehensive security remediation plan to address critical vulnerabilities discovered in the HVAC Community Events plugin's event creation form through automated security testing. The plan provides a systematic approach to eliminate all identified security issues while maintaining the enhanced UI/UX functionality.
## Vulnerability Assessment Results
### CRITICAL VULNERABILITIES IDENTIFIED:
```
┌─────────────────────────────────────────────────────────────────┐
│ SECURITY TEST RESULTS │
├─────────────────────────────────────────────────────────────────┤
│ [CRITICAL] XSS Vulnerability in Rich Text Editor │
│ - Script tags pass through unfiltered │
│ - Malicious content stored in form data │
│ - Risk: Session hijacking, data theft │
├─────────────────────────────────────────────────────────────────┤
│ [HIGH] File Upload Security Bypass │
│ - PHP files accepted without validation │
│ - Risk: Remote code execution │
├─────────────────────────────────────────────────────────────────┤
│ [HIGH] Missing CSRF Protection │
│ - No token validation visible │
│ - Risk: Cross-site request forgery │
├─────────────────────────────────────────────────────────────────┤
│ [MEDIUM] Form Validation Failures │
│ - Required fields not enforced │
│ - Risk: Data integrity issues │
├─────────────────────────────────────────────────────────────────┤
│ [MEDIUM] Security Control Gaps │
│ - No input length limits │
│ - Risk: DoS via large payloads │
└─────────────────────────────────────────────────────────────────┘
```
## Implementation Plan
### PHASE 1: IMMEDIATE CRITICAL FIXES (URGENT)
#### 1.1 XSS Vulnerability Remediation
**Target Files:**
- `assets/js/hvac-tec-tickets.js` (lines 68, 77)
- `includes/class-hvac-event-form-builder.php`
**Implementation:**
```javascript
// CURRENT VULNERABLE CODE (hvac-tec-tickets.js):
editor.innerHTML = hiddenTextarea.value;
textarea.value = editor.innerHTML;
// SECURE REPLACEMENT:
const cleanContent = DOMPurify.sanitize(hiddenTextarea.value, {
ALLOWED_TAGS: ['p', 'br', 'strong', 'em', 'ul', 'ol', 'li', 'a'],
ALLOWED_ATTR: ['href', 'title'],
ALLOW_DATA_ATTR: false
});
editor.innerHTML = cleanContent;
// Server-side sanitization backup:
textarea.value = DOMPurify.sanitize(editor.innerHTML, {
ALLOWED_TAGS: ['p', 'br', 'strong', 'em', 'ul', 'ol', 'li', 'a'],
ALLOWED_ATTR: ['href', 'title']
});
```
**Server-side Implementation:**
```php
// Add to class-hvac-event-form-builder.php
private function sanitize_rich_text_content($content) {
$allowed_html = array(
'p' => array(),
'br' => array(),
'strong' => array(),
'em' => array(),
'ul' => array(),
'ol' => array(),
'li' => array(),
'a' => array(
'href' => array(),
'title' => array()
)
);
return wp_kses($content, $allowed_html);
}
```
#### 1.2 File Upload Security Implementation
**Target Files:**
- `includes/class-hvac-event-form-builder.php`
**Implementation:**
```php
private function validate_file_upload($file) {
// MIME type whitelist
$allowed_types = array(
'image/jpeg',
'image/png',
'image/gif',
'application/pdf'
);
// File extension whitelist
$allowed_extensions = array('jpg', 'jpeg', 'png', 'gif', 'pdf');
// Validate MIME type
if (!in_array($file['type'], $allowed_types)) {
return new WP_Error('invalid_file_type',
__('File type not allowed. Only JPEG, PNG, GIF, and PDF files are permitted.', 'hvac-community-events'));
}
// Validate file extension
$file_extension = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
if (!in_array($file_extension, $allowed_extensions)) {
return new WP_Error('invalid_file_extension',
__('File extension not allowed.', 'hvac-community-events'));
}
// File size limit (5MB)
if ($file['size'] > 5 * 1024 * 1024) {
return new WP_Error('file_too_large',
__('File size exceeds 5MB limit.', 'hvac-community-events'));
}
// Additional security checks
if ($file['error'] !== UPLOAD_ERR_OK) {
return new WP_Error('upload_error',
__('File upload failed.', 'hvac-community-events'));
}
return true;
}
private function handle_secure_file_upload($file) {
$validation_result = $this->validate_file_upload($file);
if (is_wp_error($validation_result)) {
return $validation_result;
}
// Move file to secure location outside web root
$upload_dir = wp_upload_dir();
$secure_dir = $upload_dir['basedir'] . '/hvac-events/';
if (!file_exists($secure_dir)) {
wp_mkdir_p($secure_dir);
// Add .htaccess to prevent direct access
file_put_contents($secure_dir . '.htaccess', 'deny from all');
}
$filename = sanitize_file_name($file['name']);
$unique_filename = wp_unique_filename($secure_dir, $filename);
$file_path = $secure_dir . $unique_filename;
if (move_uploaded_file($file['tmp_name'], $file_path)) {
return array(
'filename' => $unique_filename,
'path' => $file_path,
'url' => $this->get_secure_file_url($unique_filename)
);
}
return new WP_Error('upload_failed',
__('Failed to save uploaded file.', 'hvac-community-events'));
}
```
#### 1.3 CSRF Protection Implementation
**Target Files:**
- All template files with forms
- `includes/class-hvac-tec-tickets.php` (AJAX handlers)
- `assets/js/hvac-tec-tickets.js`
**Template Implementation:**
```php
// Add to all form templates
```
**AJAX Handler Protection:**
```php
// Update all AJAX handlers in class-hvac-tec-tickets.php
public function ajax_create_event_tickets(): void {
// Security check
if (!wp_verify_nonce($_POST['hvac_event_nonce'] ?? '', 'hvac_event_create')) {
wp_send_json_error(array(
'message' => __('Security check failed. Please refresh the page and try again.', 'hvac-community-events')
));
return;
}
// Capability check
if (!current_user_can('edit_posts')) {
wp_send_json_error(array(
'message' => __('You do not have permission to perform this action.', 'hvac-community-events')
));
return;
}
// Continue with existing logic...
}
```
**JavaScript Updates:**
```javascript
// Update AJAX requests to include nonce
const formData = new FormData();
formData.append('action', 'hvac_create_event');
formData.append('hvac_event_nonce', document.querySelector('[name="hvac_event_nonce"]').value);
// Add other form data...
fetch(ajaxurl, {
method: 'POST',
body: formData
})
```
### PHASE 2: COMPREHENSIVE SECURITY HARDENING
#### 2.1 Input Validation and Sanitization
```php
private function validate_and_sanitize_input($data) {
$sanitized = array();
// Event title
$sanitized['post_title'] = sanitize_text_field($data['post_title'] ?? '');
if (strlen($sanitized['post_title']) < 3) {
return new WP_Error('title_too_short',
__('Event title must be at least 3 characters.', 'hvac-community-events'));
}
// Event description
$sanitized['post_content'] = $this->sanitize_rich_text_content($data['post_content'] ?? '');
// Date validation
if (!empty($data['event_date'])) {
$date = DateTime::createFromFormat('Y-m-d', $data['event_date']);
if (!$date || $date->format('Y-m-d') !== $data['event_date']) {
return new WP_Error('invalid_date',
__('Invalid event date format.', 'hvac-community-events'));
}
$sanitized['event_date'] = $date->format('Y-m-d');
}
return $sanitized;
}
```
#### 2.2 Rate Limiting Implementation
```php
private function check_rate_limit($user_id = null) {
$user_id = $user_id ?: get_current_user_id();
$key = 'hvac_form_submit_' . $user_id;
$attempts = get_transient($key) ?: 0;
if ($attempts >= 10) { // 10 attempts per hour
return new WP_Error('rate_limit_exceeded',
__('Too many attempts. Please wait before trying again.', 'hvac-community-events'));
}
set_transient($key, $attempts + 1, HOUR_IN_SECONDS);
return true;
}
```
#### 2.3 Enhanced Error Handling
```php
private function handle_secure_error($error, $context = '') {
// Log error for debugging (without sensitive data)
error_log(sprintf(
'[HVAC Security] %s: %s (Context: %s)',
current_time('mysql'),
$error->get_error_message(),
$context
));
// Return generic error to user
return new WP_Error('security_error',
__('A security error occurred. Please try again or contact support.', 'hvac-community-events'));
}
```
### PHASE 3: TESTING & VALIDATION
#### 3.1 Security Test Suite Expansion
```javascript
// Enhanced XSS testing scenarios
const xssPayloads = [
'',
'
',
'