docs: add security audit doc
This commit is contained in:
@@ -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+`
|
||||||
Reference in New Issue
Block a user