docs: security profile and audit checklist
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
# Security Profile
|
||||
|
||||
## Audit Status
|
||||
|
||||
**Grade: A+ — 30/30 checks — Last audit: 2026-05-31**
|
||||
|
||||
## Authentication Stack
|
||||
|
||||
| Layer | Implementation |
|
||||
|---|---|
|
||||
| Transport | Bearer token in `Authorization` header |
|
||||
| Token format | HMAC-SHA256 JWT, 1-hour expiry |
|
||||
| Signing secret | 64-char hex (256-bit), stored in `wp_options` as `asktam_mcp_jwt_secret` |
|
||||
| JWT claims | `key_id`, `iss` (site URL), `exp`, `jti` (revocable) |
|
||||
| Comparison | `hash_equals()` — timing-safe |
|
||||
| Key storage | bcrypt hash in `mwp_asktam_mcp_keys.key_hash` |
|
||||
| Revocation | JTI revocation list in `wp_options` |
|
||||
| Secret rotation | `TokenManager::rotateSecret()` — invalidates all existing tokens |
|
||||
|
||||
## Scope Enforcement
|
||||
|
||||
Every tool call validates the required scope against the key's granted scopes:
|
||||
|
||||
```
|
||||
read → read-only operations
|
||||
write → create / update / delete
|
||||
admin → plugin mgmt, CLI, raw SQL, options
|
||||
elementor → Elementor builder tools
|
||||
woo → WooCommerce tools
|
||||
```
|
||||
|
||||
## Rate Limiting
|
||||
|
||||
- Default: 60 requests/minute per API key
|
||||
- Stored via WP transients (`asktam_mcp_rate_{key_id}`)
|
||||
- Configurable in WP Admin → AskTam MCP → Settings
|
||||
- Returns HTTP 429 on exceed
|
||||
|
||||
## HTTPS Enforcement
|
||||
|
||||
When enabled (default: on), requests over HTTP are rejected with 403.
|
||||
Configurable in Settings tab.
|
||||
|
||||
## Input Sanitization
|
||||
|
||||
| Attack vector | Protection |
|
||||
|---|---|
|
||||
| SQL injection | `wpdb->prepare()` everywhere, `(int)` casts on IDs |
|
||||
| XSS | 47 `esc_*()` calls in AdminMenu |
|
||||
| CSRF | `wp_verify_nonce()` on all 3 admin form actions |
|
||||
| Path traversal | `realpath()` + uploads/ sandbox in FileManager |
|
||||
| Shell injection | Allowlisted commands + `escapeshellarg()` in CLI |
|
||||
| Raw SQL abuse | SELECT-only enforcement + disabled by default |
|
||||
|
||||
## Audit Logging
|
||||
|
||||
Every tool call is logged to `mwp_asktam_mcp_log`:
|
||||
- `key_id` (not raw token)
|
||||
- `tool` name
|
||||
- `ip` address
|
||||
- `status` (success/error)
|
||||
- `duration_ms`
|
||||
- `created_at`
|
||||
|
||||
Viewable in WP Admin → AskTam MCP → Audit Log (last 1000 entries).
|
||||
|
||||
## Raw SQL
|
||||
|
||||
Disabled by default. When enabled, only `SELECT` statements are allowed. All DML (`INSERT`, `UPDATE`, `DELETE`, `DROP`, `TRUNCATE`, etc.) is blocked via pattern matching.
|
||||
|
||||
## File Manager Sandbox
|
||||
|
||||
Restricted to `wp_upload_dir()['basedir']` via `realpath()` verification. Any attempt to traverse outside uploads/ returns an error.
|
||||
|
||||
## CLI Allowlist
|
||||
|
||||
Only explicitly allowed WP-CLI commands are executable. All arguments are passed through `escapeshellarg()`. The `--allow-root` flag is always appended (required since container runs as root).
|
||||
|
||||
## 30-Check Audit Points
|
||||
|
||||
1. Bearer token check present in request flow
|
||||
2. Bearer token extraction from Authorization header
|
||||
3. HTTPS enforcement code path in Auth::validate()
|
||||
4. HTTPS enforcement enabled in settings
|
||||
5. Rate limiting via transients
|
||||
6. Scope enforcement per request
|
||||
7. `hash_equals()` for timing-safe HMAC comparison
|
||||
8. HMAC-SHA256 algorithm used
|
||||
9. JWT `exp` claim validated
|
||||
10. JWT `iss` claim validated against site URL
|
||||
11. JTI revocation list implemented
|
||||
12. JWT secret rotation supported
|
||||
13. JWT secret is 64+ chars
|
||||
14. CSRF: `wp_verify_nonce` on admin form actions (3+ checks)
|
||||
15. XSS: 20+ `esc_*()` calls in AdminMenu
|
||||
16. `wpdb->prepare()` in TokenManager queries
|
||||
17. `(int)` casts on post_id in PostTools
|
||||
18. SELECT-only enforcement in RawSqlTools
|
||||
19. Raw SQL disabled by default
|
||||
20. FileManager sandboxed to uploads dir
|
||||
21. CLI allowlist present
|
||||
22. CLI injection blocking present
|
||||
23. `escapeshellarg()` in CLI
|
||||
24. `--allow-root` flag in CLI (container runs as root)
|
||||
25. Rate limit configured (> 0, ≤ 600)
|
||||
26. Request logging enabled
|
||||
27. Audit log table exists
|
||||
28. Log table stores key_id only (not raw tokens)
|
||||
29. At least one active API key exists
|
||||
30. Admin-scoped keys are labeled
|
||||
Reference in New Issue
Block a user