Go Back to Parent Doc

Security & Privacy

Sokket opens your WordPress site to an AI agent. That is exactly the kind of thing that deserves a careful security model, so here is the whole of it.

The guarantee: no outbound calls

This plugin makes no outbound requests to any AI provider, or to any other external service. Not for telemetry, not for updates to a vendor, not for anything. It has no AI SDK, no API key storage, and no code path that connects out.

That isn’t a setting you could accidentally flip — it’s an architectural rule the codebase is written to. There is no wp_remote_* call, no download_url(), and no file_get_contents() on a caller-supplied target anywhere in the tool layer. The clearest example is upload_media: it takes base64 bytes inside the request rather than a URL to go and fetch, precisely so that enabling image uploads doesn’t create an outbound request — or an SSRF surface.

Sokket only ever receives connections, from clients you configured, on an endpoint you can switch off in one click.

Off until you turn it on

  • The MCP server is disabled after activation. Requests are rejected before the body is even parsed.
  • OAuth 2.1 is disabled, and its discovery documents return 404 while it is.
  • Every write tool is off on every new token.
  • No credential exists until you create one.

A fresh install is inert.

The three gates

Every tool call passes all three, in order:

  1. The connection’s tool allowlist — is this tool ticked for this credential?
  2. The read-only ceiling — if the connection is read-only, every write tool is refused regardless of the allowlist.
  3. A real capability check — the request runs as the bound WordPress user, and current_user_can() is called against the tool’s mapped capability.

Gate 3 is the one that matters most: the token is never trusted on its own. Even a stolen token can only do what its user could already do in wp-admin, minus everything you didn’t tick.

Tools whose real permission is per-object check again inside the callback: update_post and set_featured_image re-check edit_post for that specific post, moderate_comment re-checks edit_comment for that comment, and the term tools re-check the taxonomy’s own edit_terms / assign_terms capabilities. The definition’s capability is only the outer gate.

How credentials are stored

  • Bearer tokens are stored as a SHA-256 hash. The plaintext is displayed exactly once and never again — the plugin cannot recover it.
  • OAuth access tokens, refresh tokens, authorization codes, and client secrets are stored as hashes too, and looked up without caching.
  • Comparisons are timing-safe.
  • Revoking any credential takes effect on the very next request.

Transport hardening

  • Origin validation. Requests carrying an Origin header from another host are rejected — DNS-rebinding protection for the browser case. Native MCP clients don’t send one.
  • Rate limiting. 120 requests per minute per credential, tracked in transients; over the limit returns 429.
  • Sessions. A successful initialize issues an Mcp-Session-Id backed by a transient with a 15-minute sliding window. An unknown or expired session gets a 404 so the client re-initializes cleanly, and a DELETE ends one on request.
  • No server-initiated stream. GET on the endpoint returns 405. The server responds to requests; it never pushes.
  • Spec-correct errors. Failures come back as JSON-RPC error objects, not as WordPress error blobs that leak internals.

Upload restrictions

If you enable upload_media, these limits apply and cannot be configured away from the client side:

  • Raster images only — JPEG, PNG, GIF, WebP, AVIF. SVG is refused unconditionally, including on sites that permit SVG uploads elsewhere or set unfiltered_upload, because SVG is XML that can carry script.
  • The MIME type is derived from the decoded bytes, never the file name, and the stored extension is rewritten to match the real data.
  • Per-file and hourly caps — 20 files and 25 MB per user per hour by default, plus a per-file size limit. All filterable, for sites that need different numbers.
  • The parent post is permission-checked when post_id is supplied.

What an AI client can actually see

Whatever the bound user can see, through the tools you enabled — no more. Two cases worth deciding on deliberately:

  • list_comments returns commenter email addresses.
  • get_site_settings includes the site’s admin email in the general group.

Both are data that user already sees in wp-admin. If you’d rather not share them with a client, leave those tools unticked.

Note also that the AI client itself is a third party with its own privacy policy. Sokket controls what leaves your site through the endpoint; it can’t control what your client’s vendor does with data you send them. Grant narrowly for that reason as much as any other.

What is deliberately absent

The free plugin ships no filesystem-write tool, no arbitrary file-read tool, no database query tool, no WP-CLI passthrough, and no plugin or theme installer. Nothing executes arbitrary input, and nothing writes outside the posts, media, terms, and comments APIs.

The one tool that touches the filesystem, get_php_error_log_tail, is constrained to the path from ini_get( 'error_log' ) — never a caller-supplied path — capped at 100 lines, and gated on manage_options.

Likewise get_site_settings reads from a hard-coded option allowlist. The caller cannot name an option; there is no code path that reads an arbitrary one.

Admin-side hardening

Every admin action requires manage_options and a valid nonce. Input is sanitized on the way in and escaped on the way out; database queries are prepared, with %i placeholders for table names. The plugin is built to run clean through PHPCS with the WordPress standard and through Plugin Check.

The audit trail

Every tool call is recorded with the timestamp, user, tool, outcome, and the id of the object it acted on. Arguments are never stored — so the log tells you what happened without becoming a second copy of your content. See Audit Log.

A practical checklist

  • Serve the site over HTTPS. A bearer token over plain HTTP is a token in the clear.
  • Bind connections to the least-privileged user that can do the job. This is the single highest-leverage choice on the page.
  • Start read-only, and grant writes only when you know what the agent does with them.
  • Never commit a token to a repository — .cursor/mcp.json and .vscode/mcp.json are the usual accidents.
  • Give each machine and client its own labelled token, so revoking one doesn’t disturb the rest.
  • Check the audit log after the first few sessions.
  • Revoke tokens you’ve stopped using. They don’t expire on their own.
  • Switch the server off entirely when you’re not using it — one checkbox, and the endpoint is closed.

Reporting a vulnerability

Found something? Please report it privately rather than in a public forum: open a support ticket or contact BeautifulPlugins directly, with enough detail to reproduce it.

Related

Shopping Cart
  • Your cart is empty.