Skip to main content
Cloud holds two kinds of secret for you: your database credentials and your agent tokens. This page is how each is protected, and how customers and regions are isolated from one another. The policy engine is the runtime guard; this is the storage and isolation model underneath it. You sign in to the dashboard with email and password, or Google.

Managed credential encryption

When you paste a Postgres URL, Cloud encrypts it before it touches the database. In production, credentials are encrypted with AES-256-GCM using a per-region AWS KMS key — one CMK per region, not one per tenant — via envelope encryption: KMS generates a data key, the DSN is sealed under it. The ciphertext is bound to your account and region with an encryption context of {customerId, region}, enforced on both encryption and decryption. A decrypt request for the wrong customer or the wrong region fails closed — the credential can’t be decrypted out of context, even with access to the ciphertext. The plaintext DSN is never persisted. It’s encrypted on the way in and only ever decrypted in-region to spawn the engine for a request.

Tokens stored as HMAC digests

Machine tokens are never stored in plaintext. Each token is hashed with HMAC-SHA256 under a per-region secret and only the digest is kept. When an agent presents a token, Cloud hashes the presented value and compares digests in constant time. This is why a token’s full value can be shown only once, at mint time: there’s no stored plaintext to show you later — only the digest and a short prefix/suffix for recognition.

Per-agent least-privilege scope

Each agent credential reaches only the databases you grant it, at the access level you set — read or read/write. An agent never sees a database it wasn’t granted, and a credential carrying no grant fails closed: an agent that connects over OAuth with no database access is rejected, not silently given the whole project. This is least privilege at the credential, on top of the per-database policy the engine enforces on every query.

Roles

Sensitive dashboard actions are restricted to owners and admins; members connect agents and query. See roles.

Row-level security for audit

The hosted audit log is shared infrastructure, isolated per customer with Postgres row-level security. Every audit query is scoped to the requesting account’s rows by the database itself — isolation is enforced at the row level, not only in application code, and the policy is forced so even a privileged database role can’t read across customers.

Region locality of secrets

Your region choice is a hard boundary for your secrets:
  • Credentials are encrypted under that region’s KMS key.
  • Tokens are hashed under that region’s HMAC secret.
  • Audit rows live in that region’s database.
The keys are physically separated per region, and the KMS encryption context pins each decrypt to its region. A compromise of one region cannot decrypt or forge the other region’s secrets — a US-region incident leaves EU credentials and tokens cryptographically out of reach, and vice versa. This is why the region choice is immutable: it’s a real isolation boundary, not a label.

Browser hardening headers

The dashboard sends a set of security response headers on every route — landing, sign-in, and the authenticated app alike:
  • Content-Security-Policy: frame-ancestors 'none' and X-Frame-Options: DENY — the origin can’t be embedded in a cross-site iframe, so the dashboard can’t be clickjacked.
  • X-Content-Type-Options: nosniff — no MIME sniffing.
  • Referrer-Policy: strict-origin-when-cross-origin — referrers don’t leak full URLs cross-origin.
  • Permissions-Policy: camera=(), microphone=(), geolocation=() — the page asks for no device APIs.
  • Strict-Transport-Security with a two-year max-age, includeSubDomains, and preload — browsers stay on HTTPS.

Defense in depth

Cloud’s encryption and isolation sit on top of the same enforcement self-hosters get — they don’t replace your database’s own permissions, so give each project’s databases a least-privilege database role as well. See the threat model for what Midplane does and doesn’t claim, and what’s in and out of scope.

Threat model

What Midplane claims and doesn’t, and what’s in and out of scope.

Adversarial corpus

The bypass attempts pinned as permanent regression tests.