Security audit and bug fixes (v0.12.0)
All checks were successful
Create Release Package / build-release (push) Successful in 1m37s

- Complete security audit for WordPress best practices, OWASP Top 10
- Fix Calculator static method calls in API controllers
- Fix EmailNotifier method names in BookingsController
- Fix guest_id type casting in EmailNotifier

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-04 09:44:23 +01:00
parent a8e0df99d1
commit dbd0f3f788
8 changed files with 117 additions and 24 deletions

View File

@@ -1268,3 +1268,70 @@ Admin features always work; frontend requires valid license.
- v0.11.2: Calendar room column width and building name display
- v0.11.3: Calendar filters side-by-side layout
- Both versions tagged and pushed to origin
### 2026-02-04 - Version 0.12.0 (Security Audit)
**Completed:**
- Comprehensive security audit (Phase 12)
- WordPress best practices compliance verification
- OWASP Top 10 vulnerability review
- Live API endpoint testing against localhost:9080
**Security Audit Findings:**
1. **SQL Injection:** ✓ PROTECTED
- All `$wpdb` queries use `$wpdb->prepare()` with parameterized queries
- WP_Query used throughout for post queries (inherently safe)
- Format specifiers (`%s`, `%d`) properly used in `$wpdb->update()` calls
2. **XSS (Cross-Site Scripting):** ✓ PROTECTED
- PHP output consistently uses `esc_html()`, `esc_attr()`, `esc_url()`
- JavaScript uses `escapeHtml()` function (textContent/innerHTML pattern)
- Form values properly escaped before output
3. **CSRF (Cross-Site Request Forgery):** ✓ PROTECTED
- All forms use `wp_nonce_field()`
- Admin AJAX handlers use `check_ajax_referer()` or `wp_verify_nonce()`
- Capability checks with `current_user_can()` on privileged operations
- Public AJAX endpoints are read-only and don't modify data
4. **REST API Security:** ✓ PROTECTED
- Permission callbacks on all admin endpoints (`admin_permission`)
- Rate limiting via transient-based `RateLimiter` class
- Input sanitization via `sanitize_callback` on all parameters
- Sensitive data (ID/passport) not exposed via API
5. **Data Encryption:** ✓ IMPLEMENTED
- Guest ID/passport numbers encrypted with AES-256-CBC
- IV stored with encrypted data for secure decryption
**Bugs Fixed During Audit:**
- Fixed `Calculator::calculate()` being called statically (non-static method)
- `src/Api/Controllers/BookingsController.php`
- `src/Api/Controllers/RoomsController.php`
- `src/Api/Controllers/PricingController.php`
- Fixed incorrect EmailNotifier method names in BookingsController
- `send_admin_notification``send_admin_new_booking`
- `send_cancellation_email``send_cancellation`
- `send_confirmation_email``send_guest_confirmation`
- Fixed guest_id type casting in EmailNotifier (string from post meta → int)
**Files Changed:**
- `src/Api/Controllers/BookingsController.php` - Calculator instantiation, EmailNotifier method names
- `src/Api/Controllers/RoomsController.php` - Calculator instantiation
- `src/Api/Controllers/PricingController.php` - Calculator instantiation
- `src/Booking/EmailNotifier.php` - guest_id type casting
- `wp-bnb.php` - Version bump to 0.12.0
- `CHANGELOG.md` - Added v0.12.0 security audit notes
- `PLAN.md` - Marked Phase 12 complete
**Learnings:**
- `get_post_meta()` always returns strings; cast to `(int)` when needed for type-hinted methods
- Static vs instance method calls must match the method declaration
- Public frontend AJAX endpoints can safely skip nonce verification if they're read-only
- Rate limiting headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`) provide client feedback
- WordPress REST API permission callbacks should use capability checks, not user login status alone