docs: add security audit doc

This commit is contained in:
2026-05-31 12:42:29 +00:00
parent ba8dddc140
commit d34d6cbd81
+142
View File
@@ -0,0 +1,142 @@
# 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+`