# Security ## Audit Result **Grade: A+ — 30/30 checks passed** (last run: 2026-05-31) Zero findings. All checks pass. --- ## Security Checklist ### Authentication | Check | Status | |---|---| | Server.php calls Auth::validate() on every request | ✅ | | Bearer token extraction in Auth::extractToken() | ✅ | | HTTPS enforcement code path in Auth::validate() | ✅ | | HTTPS enforcement ENABLED in settings | ✅ | | Rate limiting via transients (60 req/min) | ✅ | | Scope enforcement per tool | ✅ | ### Cryptography | Check | Status | |---|---| | hash_equals() for timing-safe HMAC comparison | ✅ | | HMAC-SHA256 used for JWT signing | ✅ | | JWT expiry (exp) checked on every verify | ✅ | | JWT issuer (iss) validated against site URL | ✅ | | JTI revocation list implemented | ✅ | | JWT secret rotation supported | ✅ | | JWT secret is 64 hex chars (256-bit) | ✅ | ### Admin Forms | Check | Status | |---|---| | wp_verify_nonce on 3+ admin actions | ✅ | | 47+ esc_*() calls in AdminMenu | ✅ | ### SQL Injection | Check | Status | |---|---| | wpdb->prepare() used in TokenManager key lookups | ✅ | | (int) casts on post_id in PostTools | ✅ | | SELECT-only enforcement in RawSqlTools | ✅ | | Raw SQL disabled by default in settings | ✅ | ### File / CLI Safety | Check | Status | |---|---| | FileManager sandboxed to wp_upload_dir() | ✅ | | CLI command allowlist + injection block | ✅ | | escapeshellarg() on all CLI args | ✅ | | --allow-root flag set (container runs as root) | ✅ | ### Logging & Privacy | Check | Status | |---|---| | Rate limit configured (60 req/min) | ✅ | | Request logging ENABLED | ✅ | | Audit log table exists | ✅ | | Log table stores key_id only (not raw token) | ✅ | | Active API keys present | ✅ | --- ## Rate Limiting Enforced via WP transients, keyed per API key: ``` transient key: asktam_mcp_rate_{key_id} value: request count in current window expiry: 60 seconds (configurable) default limit: 60 requests/minute ``` Configure in WP Admin → AskTam MCP → Settings. --- ## HTTPS Enforcement When enabled (default), requests over plain HTTP are rejected with: ```json {"error": "https_required", "message": "HTTPS required"} ``` Configured in WP Admin → AskTam MCP → Settings → Require HTTPS. --- ## Raw SQL Disabled by default. When enabled (Settings tab), only `SELECT` statements are accepted. The following patterns are blocked regardless: - `INSERT`, `UPDATE`, `DELETE`, `DROP`, `TRUNCATE`, `ALTER`, `CREATE`, `GRANT`, `REVOKE` - Multiple statements (`;` separator) - Stored procedure calls Enable only temporarily when needed. Disable immediately after. --- ## CLI Sandboxing `CliTools.php` enforces two layers: **1. Command allowlist** — only specific WP-CLI commands permitted (defined in `ALLOWED_COMMANDS` constant). **2. Injection block** — `BLOCKED_PATTERNS` array prevents shell injection characters. **3. Arg escaping** — all arguments passed through `escapeshellarg()`. **4. Root flag** — `--allow-root` appended automatically (container runs as root). --- ## Audit Log Every tool call is logged to `mwp_asktam_mcp_log`: ``` key_id, tool_name, ip_address, status, duration_ms, created_at ``` Raw API keys and JWT tokens are never stored. Only `key_id` is logged. View last 1000 entries in WP Admin → AskTam MCP → Audit Log. --- ## Running the Security Audit Test script at `/tmp/security_audit_v2.php` on the VPS. Run via: ```bash docker cp /tmp/security_audit_v2.php mainwp:/tmp/security_audit_v2.php docker exec mainwp php /tmp/security_audit_v2.php ``` Expected output: `SCORE: 30/30 — Grade: A+`