Security is the product. Here is the architecture.
Gentkey holds your credentials and stands between AI agents and your accounts, so this page is specific: what is encrypted and how, what the policy gate checks before any call reaches an upstream service, and what gets recorded. Everything below describes enforcement in the shipped code — not intentions.
Encrypted at rest, bound to one connection, never in model context.
Connector credentials — OAuth tokens, API keys, App Store Connect .p8 keys — are encrypted with AES-256-GCM before they touch the database. In production the encryption and decryption happen inside Google Cloud KMS: the key lives in the KMS and never leaves it, so a copy of the database alone cannot decrypt anything.
Every ciphertext is bound to its connection id as additional authenticated data. A ciphertext moved onto another connection row — by a bug or by an attacker with database access — fails to decrypt rather than decrypting in the wrong context.
Credentials are decrypted server-side at call time and injected into the upstream request. No stored credential ever enters a model’s context window, an agent’s config file, or a tool response. Agents authenticate to Gentkey with OAuth; Gentkey holds the service credential.
Grants are scoped per capability — and classification fails closed.
Connecting an account only ever grants reads, and reads can be switched off per connection. Every write capability must be granted explicitly, stands until revoked, and is checked fresh on every call — revoking a grant denies the very next write.
Where a connector can classify a call, grants are typed to what the call actually does: google-ads.campaignBudgets.mutate is a different grant from google-ads.campaigns.mutate, and a BigQuery INSERT is a different grant from a DROP TABLE(statements are classified by Google’s own parser in a free dry run, not by Gentkey guessing at SQL). Classification can only add narrower ways for a call to be authorized — anything mixed, unclassifiable, or newly shipped by a vendor falls through to the connector’s broad write grant. Unknown writes are never waved through.
Connections can also be scoped to specific accounts. The scoping check runs centrally in the gate, for reads and writes alike, so an individual connector cannot forget it.
Dollar and velocity bounds, enforced by arithmetic before the call.
Grants carry typed constraints: max $ change per call on budget grants, plus rolling-window limits — max_writes_per_hour, max_targets_per_hour, max_usd_per_hour, max_usd_per_day. The gate prices the impending write and checks it against the windows before the upstream service sees the request; a $500 budget change under a $50-per-call cap is denied without reaching the vendor.
The velocity check and its ledger entry happen in one database transaction under an advisory lock, so concurrent calls cannot race past a limit. If a write fails after reserving its slot, the reservation is released; if that release fails, the window overcounts — errors land on the side of denying too much, not allowing too much.
When one call matches both a narrow grant and a broader one, it must satisfy every matched window: a broad grant’s rate limit stays a ceiling over the narrow grants that overlap it.
A hard plan/commit boundary.
Curated write tools are implemented in two phases: plan()computes exactly what would change — including constraint checks and current usage against the grant’s windows — and commit() is the only code allowed to perform the side effect. Tools built this way advertise a dry_run argument; on a dry run the gateway never calls commit(), so the preview is a structural guarantee, not a convention.
Denials for a missing grant are previewable too: you can see exactly what an agent would have done before deciding whether to grant it.
An emergency stop that beats every grant.
One flip from the dashboard denies every write the freezer controls — their own agents’ calls everywhere, and every connection they own or administer, including connections a teammate created and shared into their org. The freeze is checked on every call with no caching, so it lands instantly on live sessions. Reads stay up, so you can watch what agents are attempting while you decide what to revoke.
This is why Gentkey uses standing grants instead of per-call approval prompts: revocation is instant and total, without training anyone to click “approve”.
Every decision recorded — allowed and denied alike.
Every tool call through the gateway lands in the audit log: the agent (OAuth client) that made it, the run that grouped it, the tool, the capability it resolved to, the verdict — allowed, denied, denied by constraint, or dry run — and the reason, including the grant that authorized it or the grant that would have. Denials are first-class records, not dropped requests.
The application only ever appends to the log; nothing in the product updates or deletes audit rows. Recorded arguments are sanitized so the trail can’t become a second credential store: secret-shaped keys are redacted, and strings, arrays, and payload sizes are capped. Where a connector can supply them, rows also carry the provider’s request ids and before/after state for forensics.
Outbound requests are guarded, not trusted.
Gentkey’s server fetches URLs that users and upstream servers choose — custom MCP server URLs, and every OAuth endpoint an upstream’s discovery metadata declares. Each outbound request is validated first: https only, cloud metadata hosts blocked, and DNS resolution checked against private address ranges on every request, so a host that later re-points at an internal IP is caught on its next use.
Redirects are followed manually so every hop is re-validated against the same rules, and on a cross-origin hop the authorization and cookie headers are dropped — a redirect can’t exfiltrate an upstream credential. Response bodies are read with a hard size cap that cuts a hostile upstream off mid-stream.
Postgres with row-level security on.
Application data lives in Postgres (Supabase, hosted in the United States) with row-level security enabled on every table and no policies granted — deny-all for every role but the application’s own. Supabase’s Data API roles additionally have their table, sequence, and function grants revoked, including on future tables, so the publishable anon key reaches nothing. Tenant isolation is also enforced in the application layer: one user’s agents can never see another user’s connections.
What we don’t claim.
Gentkey has not undergone a SOC 2 audit. If a compliance report is a hard requirement for you today, we are not there yet — this page exists so you can evaluate the actual architecture instead of a badge. When that changes, this section will say so.
Found something?
Report vulnerabilities to hector@instasize.com(a dedicated security@ address is coming; until then this reaches the founder directly). Include enough detail to reproduce. You’ll get a human reply, a fix on a timeline we’ll agree on, and credit if you want it. Please don’t access other users’ data while demonstrating an issue.
Cut smaller keys.
Connect an account and grant your first scoped capability in under a minute.