Files
advanced-mcp-plugin/docs/04-SECURITY.md
T

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)
  • 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