Pressocampus handles personal data — your thoughts, preferences, and decisions. Security is not an afterthought.
Pressocampus uses OAuth 2.1 with PKCE as its sole authentication method. There are no API keys, application passwords, or unauthenticated endpoints.
- Standard — the same protocol used by banks, Google, and GitHub. Every modern AI client knows how to use it.
- No credentials in config files — you never put your WordPress password anywhere near your AI client.
- Granular revocation — you can disconnect a specific client without affecting others or changing your password.
- Short-lived access tokens — tokens expire; refresh tokens are rotated on use.
PKCE (Proof Key for Code Exchange) prevents authorization code interception attacks. Even if an attacker intercepts the authorization code during the OAuth flow, they cannot exchange it for tokens without the code verifier that only the legitimate client has.
This is especially important for AI clients that run locally, where redirect URIs are less controllable.
AI Client Pressocampus You
│ │ │
│── POST /oauth/register ────────────>│ │
│<─ client_id, client_secret ─────────│ │
│ │ │
│── GET /oauth/authorize ─────────────>│ │
│ │── Consent screen ─────────>│
│ │<─ "Allow" ─────────────────│
│<─ authorization_code ───────────────│ │
│ │ │
│── POST /oauth/token ────────────────>│ │
│<─ access_token, refresh_token ──────│ │
│ │ │
│── POST /mcp (Bearer token) ─────────>│ │
│<─ MCP response ─────────────────────│ │
AI clients register themselves automatically via POST /pressocampus/v1/oauth/register. No manual app registration required.
Registered client credentials:
- Client ID — a 32-character cryptographically secure random hex string (
bin2hex(random_bytes(16))), not a predictable time-based value. - Client secret — generated with
wp_generate_password(40)and stored as a bcrypt hash (PASSWORD_BCRYPT). The plaintext secret is returned to the client once at registration and never stored. Existing clients registered before v1.0.25 with plaintext secrets continue to work.
- JWT format, RSA-signed
- Expire after 8 hours (configurable)
- Include the WordPress user ID as the subject
- Opaque, stored hashed in the database
- Rotated on every use — the old refresh token is immediately invalidated when a new one is issued
- Expire after 30 days of inactivity
The consent screen tells users exactly what access is being granted:
[Client Name] is requesting permission to read, write, and delete memories on your Pressocampus brain.
There is a single scope: pressocampus:memory. There is no read-only mode — an authorized client has full access to your memories.
On activation, Pressocampus generates a 2048-bit RSA key pair:
- Private key — stored as a PEM string in
wp_options(key:pressocampus_rsa_private_key). Protect yourwp_optionstable and WordPress filesystem accordingly. - Public key — stored in plaintext, exposed in the OAuth authorization server metadata. Used by clients to verify token signatures.
The key pair is regenerated if the private key is ever deleted. You can see the public key fingerprint in Settings → Advanced.
The RSA key is not included in brain exports. Exports contain only memory content and metadata.
Every memory is owned by a specific WordPress user (post_author). The OAuth token identifies which user is authenticated, and all queries are automatically scoped to that user.
It is not possible for an AI client authorized as User A to read, write, or delete User B's memories. This is enforced at the database query level, not just at the API level.
To prevent abuse and accidental runaway automation:
| Operation | Limit |
|---|---|
| Read operations | 60 per minute per user |
| Write operations | 30 per minute per user |
The initialize handshake also counts against the read limit. This prevents a scenario where an attacker rapidly reconnects to trigger unbounded soul-creation database work without being throttled.
When a limit is exceeded for a tool call, the tool returns a rate_limit_exceeded error response (the MCP layer returns an isError: true content block). For resources/list and resources/read, a JSON-RPC error is returned. In both cases the HTTP status is 400.
Limits are tracked per access token using WordPress object caching (falls back to transients if no external object cache is present). An authenticated session with no token ID is denied rather than allowed to bypass throttling.
Pressocampus uses a CORS allowlist on the MCP endpoint. CORS headers (Access-Control-Allow-Origin, Access-Control-Allow-Credentials) are only sent if the requesting origin matches:
- The site's own origin (always allowed)
- An origin you've explicitly added in
Settings → Advanced → CORS
Requests without an Origin header (typical for desktop AI clients like Claude Desktop and Cursor) are unaffected by CORS — they bypass the origin check entirely.
Add browser-based AI client origins to the CORS allowlist if they send an Origin header with their requests.
OAuth 2.1 requires HTTPS. Pressocampus will not issue tokens over HTTP in production. The consent screen redirects to HTTPS if an HTTP request is received.
In local development environments (localhost), HTTP is allowed for testing.
All memory content is sanitized before storage:
- Content is stored raw (unsanitized) and escaped on output — following WordPress best practices
- MIME type is validated against an allowlist
- URI uniqueness is enforced at the database level
- Content size is validated against the configured maximum
- Unauthorized access — no token, no access
- Cross-user data access — per-user query scoping
- Token interception — PKCE in the authorization flow
- Concurrent write conflicts — ETag-based optimistic locking on memories; MySQL advisory locks (
GET_LOCK) on soul creation and index rebuilds - Runaway AI writes — rate limiting
- Accidental deletion — soul/index are protected, deletion requires explicit context
- History audit trail — every write operation is logged with agent name, timestamp, and context so you can review exactly what your AI has been doing
- A compromised WordPress admin account — if someone has admin access to your WordPress site, they have access to your memories. Secure your WordPress admin.
- A compromised AI client — if your AI client is compromised, the attacker has your OAuth tokens. Revoke from
Settings → Advanced → Connected Apps. - The WordPress host — your memories live on your server. Secure your server.
- An AI that goes rogue — Pressocampus logs everything in History. Review it periodically.
If you find a security vulnerability in Pressocampus, please report it privately by opening a GitHub Security Advisory rather than a public issue.