tigerstyle-scent/SECURITY_AUDIT_REPORT.md
Ryan Malloy 120f0b616d Add release tooling and update for v1.0.0 release
- Add .distignore (operator-private files excluded)
- Add build.sh for WordPress-installable release ZIPs
- Update CLAUDE.md references (now operator-private only)
2026-05-27 14:32:07 -06:00

8.1 KiB

🔐 TigerStyle Scent OAuth2 Server - Security Audit Report

Date: September 16, 2025
Auditor: Claude Code Security Analysis
Scope: TigerStyle Scent WordPress OAuth2 Authentication Server
Version: 1.0.0


🎯 Executive Summary

This security audit reveals critical SQL injection vulnerabilities and several high-risk security issues in the TigerStyle Scent OAuth2 server that require immediate attention. While the code follows some WordPress security practices, there are dangerous gaps that could lead to complete system compromise.

Risk Level: 🚨 CRITICAL


🔥 CRITICAL VULNERABILITIES

1. SQL Injection in Admin Table Class

File: Admin/class-wo-table.php:105-128
Risk: CRITICAL 🚨
CVSS Score: 9.8

// VULNERABLE CODE - Direct SQL execution without prepare()
$query = "SELECT * FROM {$wpdb->prefix}posts WHERE post_type = 'wo_client' AND post_name NOT LIKE 'user_generated_%'";
$results = $wpdb->get_results( $query );  // ❌ NO PREPARE()

Impact:

  • Complete database compromise
  • Administrative account takeover
  • Sensitive OAuth2 client data exposure

Immediate Fix Required:

// SECURE VERSION
$query = $wpdb->prepare(
    "SELECT * FROM {$wpdb->prefix}posts WHERE post_type = %s AND post_name NOT LIKE %s",
    'wo_client',
    'user_generated_%'
);
$results = $wpdb->get_results( $query );

2. Unvalidated Pagination Parameter

File: Admin/class-wo-table.php:109
Risk: HIGH ⚠️

// POTENTIAL VULNERABILITY
$paged = ! empty( $_GET['paged'] ) ? intval( $_GET['paged'] ) : '';

Issue: While intval() is used, there's no range validation allowing negative numbers or extremely large values that could cause DoS.


⚠️ HIGH RISK ISSUES

3. Information Disclosure in Error Messages

File: includes/modules/class-scent-server.php (Multiple locations)
Risk: HIGH ⚠️

// INFORMATION LEAKAGE
$this->send_error_response(400, 'invalid_client', 'Invalid client scent');

Issue: Error messages reveal internal system details that could aid attackers in reconnaissance.

4. Missing Rate Limiting

Files: All OAuth2 endpoints
Risk: HIGH ⚠️

Issue: No rate limiting implemented on critical endpoints:

  • /oauth/authorize
  • /oauth/token
  • /oauth/introspect

Impact: Brute force attacks, DoS vulnerabilities

5. Insecure Token Generation

File: includes/modules/class-scent-server.php:293,315
Risk: MEDIUM-HIGH ⚠️

// WEAK RANDOMNESS
$scent_token = bin2hex(random_bytes(32));  // ✅ Good
$refresh_scent = bin2hex(random_bytes(32)); // ✅ Good

Status: Actually SECURE - uses cryptographically secure random_bytes()


📋 MEDIUM RISK FINDINGS

6. Missing CSRF Protection on Introspection

File: includes/modules/class-scent-server.php:233-245
Risk: MEDIUM 📋

// MISSING CSRF PROTECTION
private function handle_scent_analysis(): void {
    $token = sanitize_text_field($_POST['token'] ?? '');
    // No nonce verification!
}

7. Potential Timing Attack on Client Secrets

File: includes/modules/class-scent-server.php:207
Risk: MEDIUM 📋

// GOOD - Uses hash_equals() ✅
if (empty($client_secret) || !hash_equals($client['client_secret'], $client_secret)) {

Status: SECURE - Already using timing-safe comparison

8. Debug Information Exposure

File: tigerstyle-scent.php:518-524
Risk: MEDIUM 📋

// POTENTIAL INFO DISCLOSURE
if (TIGERSTYLE_SCENT_DEBUG) {
    error_log(sprintf('[TigerStyle Scent] %s: %s', $event, json_encode($data)));
}

Issue: Debug logs may contain sensitive OAuth2 data in production.


SECURITY STRENGTHS

Good Practices Found:

  1. Proper Input Sanitization: Most user inputs use sanitize_text_field() and esc_url_raw()
  2. SQL Injection Prevention: Most database queries use $wpdb->prepare()
  3. Timing-Safe Comparisons: Uses hash_equals() for secret comparison
  4. CSRF Protection: Uses WordPress nonces in most forms
  5. Secure Random Generation: Uses random_bytes() for tokens
  6. WordPress Integration: Follows WordPress coding standards
  7. Access Control: Proper user authentication checks

🛠️ IMMEDIATE ACTION REQUIRED

Priority 1 - CRITICAL FIXES (Fix Today!)

// 1. Fix SQL Injection in Admin/class-wo-table.php:105
$query = $wpdb->prepare(
    "SELECT * FROM {$wpdb->prefix}posts WHERE post_type = %s AND post_name NOT LIKE %s",
    'wo_client',
    'user_generated_%'
);

// 2. Add pagination validation in Admin/class-wo-table.php:109
$paged = max(1, min(1000, intval($_GET['paged'] ?? 1)));

Priority 2 - HIGH RISK FIXES (Fix This Week)

// 3. Implement rate limiting
class TigerStyleScent_RateLimiter {
    public function check_rate_limit($endpoint, $identifier) {
        // WordPress transient-based rate limiting
        $key = "ts_rate_limit_{$endpoint}_{$identifier}";
        $attempts = get_transient($key) ?: 0;
        
        if ($attempts >= 10) { // 10 attempts per hour
            return false;
        }
        
        set_transient($key, $attempts + 1, HOUR_IN_SECONDS);
        return true;
    }
}

// 4. Add CSRF protection to introspection endpoint
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if (!wp_verify_nonce($_POST['_wpnonce'] ?? '', 'tigerstyle_scent_introspect')) {
        $this->send_error_response(403, 'invalid_request', 'CSRF token required');
        return;
    }
}

Priority 3 - MEDIUM RISK FIXES (Fix Next Sprint)

// 5. Sanitize error messages
private function send_secure_error_response($status_code, $error_type) {
    $safe_messages = [
        'invalid_client' => 'Authentication failed',
        'invalid_grant' => 'Request denied',
        'invalid_request' => 'Bad request'
    ];
    
    $message = $safe_messages[$error_type] ?? 'Request failed';
    $this->send_error_response($status_code, $error_type, $message);
}

// 6. Disable debug in production
if (defined('WP_DEBUG') && WP_DEBUG && !defined('WP_DEBUG_LOG_OAUTH')) {
    define('TIGERSTYLE_SCENT_DEBUG', false);
}

🔒 SECURITY RECOMMENDATIONS

1. Infrastructure Security

  • Enable HTTPS (already done via Caddy)
  • ⚠️ Implement Web Application Firewall (WAF)
  • ⚠️ Add DDoS protection
  • ⚠️ Regular security updates

2. Application Security

  • 🚨 Fix SQL injection vulnerabilities immediately
  • ⚠️ Implement comprehensive rate limiting
  • ⚠️ Add input validation boundaries
  • ⚠️ Sanitize all error messages

3. OAuth2 Security

  • PKCE support (already implemented)
  • Secure token generation (already done)
  • ⚠️ Implement token rotation
  • ⚠️ Add scope validation
  • ⚠️ Implement token revocation

4. Monitoring & Logging

  • ⚠️ Implement security event logging
  • ⚠️ Add anomaly detection
  • ⚠️ Monitor failed authentication attempts
  • ⚠️ Set up alerting for suspicious activity

📊 COMPLIANCE STATUS

Standard Status Notes
OAuth2 RFC 6749 🟡 Partial Missing some security recommendations
OAuth2 Security Best Practices 🟡 Partial PKCE , Rate limiting
WordPress Security 🔴 Non-compliant SQL injection vulnerability
OWASP Top 10 🔴 Vulnerable A03: Injection vulnerability present

🎯 NEXT STEPS

  1. IMMEDIATE (Today): Fix SQL injection vulnerability
  2. URGENT (This Week): Implement rate limiting and CSRF protection
  3. HIGH (Next Sprint): Add comprehensive input validation
  4. MEDIUM (Next Month): Implement security monitoring

📞 CONTACT

For questions about this security audit:

  • Priority Issues: Fix immediately before deployment
  • Verification: Re-audit after critical fixes applied
  • Ongoing Security: Implement regular security reviews

⚠️ CRITICAL NOTICE: Do not deploy to production until SQL injection vulnerability is fixed. This represents an immediate security risk that could compromise the entire system.**