3.7 KiB
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)toolnameipaddressstatus(success/error)duration_mscreated_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
- Bearer token check present in request flow
- Bearer token extraction from Authorization header
- HTTPS enforcement code path in Auth::validate()
- HTTPS enforcement enabled in settings
- Rate limiting via transients
- Scope enforcement per request
hash_equals()for timing-safe HMAC comparison- HMAC-SHA256 algorithm used
- JWT
expclaim validated - JWT
issclaim validated against site URL - JTI revocation list implemented
- JWT secret rotation supported
- JWT secret is 64+ chars
- CSRF:
wp_verify_nonceon admin form actions (3+ checks) - XSS: 20+
esc_*()calls in AdminMenu wpdb->prepare()in TokenManager queries(int)casts on post_id in PostTools- SELECT-only enforcement in RawSqlTools
- Raw SQL disabled by default
- FileManager sandboxed to uploads dir
- CLI allowlist present
- CLI injection blocking present
escapeshellarg()in CLI--allow-rootflag in CLI (container runs as root)- Rate limit configured (> 0, ≤ 600)
- Request logging enabled
- Audit log table exists
- Log table stores key_id only (not raw tokens)
- At least one active API key exists
- Admin-scoped keys are labeled