Trust
Your credentials never leave. Your data, when you use AI, does.
Two different things get conflated when people ask “is this safe?” One is your keys — the WordPress credentials that let anything act on your sites. The other is your content — the posts, settings, and results an assistant reads to do the work you asked for. Portcullis treats them very differently, and it’s worth being exact about which is which.
What we never hold
A WordPress credential. Full stop. Portcullis never stores one — your site holds only Portcullis's public keys. To reach it, Portcullis signs a short-lived, audience-bound token — sender-constrained to that one request (DPoP, RFC 9449), so a copy captured in flight is useless anywhere else — that the plugin validates offline, minted fresh for each request, scoped to the one action that request performs, and inert about a minute later. There is no password at rest to decrypt, on our side or yours. No AI model, any AI client, or your browser ever receives a key, a token that reaches WordPress, or anything that could be replayed against your sites.
The specifics behind that:
- We store no WordPress credential — anywhere. A copy of our database is site addresses and settings, and none of it opens anything. There is no password field in our database. Not encrypted, not hashed — it does not exist.
- Access is granted per request, never left switched on. Each call mints a fresh ES256 token. One door, one visit, one minute.
- Every action is off until you turn it on. Thirty-five actions, allowed per site and checked twice: once by Portcullis before the request leaves, then again on the site itself, where the token’s scope is intersected with that site’s own stored list. The second check is the one that matters — a WordPress admin switching something off revokes it there and then, without waiting for us to agree. Drafting and publishing are separate permissions, so an AI can write a post it has no way to publish.
- Your AI client never holds anything WordPress accepts. The client authenticates to us over OAuth 2.1 with PKCE S256 (RFC 7636) — no plaintext challenge, no implicit grant, and an authorization code spendable exactly once even if two exchanges race. What it gets back is a token for Portcullis: WordPress would not recognise it, and we never pass it on. The handshake runs on Cloudflare’s own OAuth library — open source, and not something we invented.
- Another agency’s fleet is not reachable from yours. Every read and write is tied to the organisation that owns the site, and all of them go through one piece of code that enforces it. Not the same check copied into fifty places, where one gets missed. Our build fails automatically if anyone writes a query that goes around it.
Running the technical evaluation? The threat model, data inventory and subprocessors are in the security whitepaper →
What is processed by an AI provider — and why we can’t prevent it entirely
An assistant can only act on data it can read. When you use an AI feature, the content that feature needs is processed by the AI model provider running it. That is inherent to AI assistance — not a leak, but a fact worth stating plainly rather than burying.
- The dashboard assistant runs on Cloudflare Workers AI. To answer you it may see the list of sites you’ve granted it, the ability names available on a site, and the results of any action you explicitly run.
- Your MCP client (whichever client you connect) processes tool results through its own model provider. Whatever a tool returns to that client is seen by that client’s provider under their terms.
We can minimize this surface, scope it, and make it revocable. We can’t promise a model provider never sees a piece of content you deliberately route through it — that would be promising the assistant works without reading anything, which isn’t a real thing.
How we keep that surface small
- Opt-in per action. AI features do nothing until you ask. Portcullis runs fine without them.
- Least exposure by default. Companion sites expose only an allowlist of abilities; the assistant sees only what a tool returns, on the sites you scope it to.
- Bounded by an allowlist, not by a prompt. A model can only ever run an action you allowed on that site — that is the limit that always holds. On top of it, the dashboard assistant normally shows a proposed change for you to approve; a change that plainly matches what you just asked for may run without a second prompt, a scheduled run runs unattended because approving the schedule was the approval, and an MCP client acts within the scope you granted at consent. Destructive governance actions need a freshly proven second factor regardless.
- Scoped & revocable. Access is per-site, org-checked on every call, and killable in one action: minting stops and the token chain goes cold — there was never a stored credential to reset.
- We don’t train on your data. Portcullis doesn’t retain or train on your fleet content. Model providers process it under their own published terms — review Cloudflare’s and your MCP client provider’s if that matters to your compliance posture.
The short version
Your AI gets the keys to nothing. To help, it reads the content you point it at — from an AI provider you can name, on sites you scope, for actions you approve, revocable at any time. We hold no credential to leak; the choice of what content to expose stays yours.
Questions about data processing or a compliance review? Email hello@portculliswp.com.