Security

AgentSwarms is self-hosted. The short version of our security model is that we are not in the path: your data stays in your Supabase project, your prompts go straight to the model provider you chose with the key you supplied, and there is no vendor-side copy of anything. What follows is what the software does about the parts you cannot see.

Architecture

Where your data is, and who can reach it.

Self-hosted by default

You run the container and you own the Supabase project. Application data, embeddings, traces and credentials live in your database, in the region you chose. There is no vendor-side copy and no call-home.

Your model keys

Model calls go directly from your deployment to the provider you configured, using your key. Prompts and completions are not proxied through us.

Data residency follows your infrastructure

Residency is whatever your Supabase region and your model provider's region are. Nothing else is involved.

Credential handling

What happens to the keys and tokens you paste in.

Encrypted at rest, not just in the database

Warehouse credentials, SaaS tokens, provider API keys, MCP tokens and integration secrets are AES-256-GCM encrypted in application code before they reach the database, keyed from PROVIDER_CREDS_SECRET. The database stores ciphertext and a per-record IV.

Authenticated encryption

GCM is authenticated: a tampered ciphertext fails to decrypt rather than returning altered data. A fresh random 96-bit IV is generated per encryption, so identical secrets do not produce identical ciphertext.

Never returned to the browser

Connection listings deliberately exclude the encrypted field entirely. Secrets are decrypted server-side, at the point of use, and are not sent to any client.

Secret references

Configuration can hold {{secret:NAME}} pointers resolved per-user at read time, so a shared configuration never embeds the secret itself. A reference that cannot be resolved stops the call and names the secret — it is never silently replaced with an empty string, which would turn a credential problem into an unauthenticated request some APIs answer with a 200.

The key can be rotated without downtime

Every ciphertext carries a fingerprint of the key that wrote it, so the deployment can accept a previous key for decryption while writing everything new with the current one. Put the new secret in PROVIDER_CREDS_SECRET, the outgoing one in PROVIDER_CREDS_SECRET_OLD, restart, then run the re-encrypt sweep in Admin → IAM → Settings. Nothing breaks mid-rotation.

The fingerprint is not key material

The key id is a separately domain-separated hash, not a slice of the AES key, so showing it in a database row and in the admin UI reveals which key wrote a value and nothing more.

Re-encryption fails safe

The sweep is idempotent — values already on the current key are skipped — and a value that cannot be decrypted under any configured key is counted and reported, then left byte-identical. A wrong keyring costs an error message, not a credential. The sweep is instance-wide, so check the counts on the Settings card before running it.

Tenant isolation

How one account's data is kept away from another's.

Row-level security

Tenant data is scoped by Postgres RLS policies on the owning user, enforced by the database rather than by application code.

Explicit scoping where RLS cannot apply

Background work — scheduled refreshes, syncs and swarm runs — executes with a service-role client, where RLS is off. Those paths pass an explicit owner filter, and the tool surface available to them is capped to a hard-coded allow-list of tools that honour it.

Shared data is masked in SQL, not in the UI

When a dataset is shared, row filters and column masks are applied by a SECURITY DEFINER database function. Masked columns are absent from the result, not hidden by the interface — so there is no view that returns them.

Read-only by construction

Every query path against a connected database is guarded to reject anything but SELECT/WITH/SHOW/DESCRIBE/EXPLAIN, and connectors are documented to use read-only credentials. Where the vendor supports it, read-only is also asserted at the server.

Governance and auditability

What you can prove after the fact.

Tamper-evident audit trail

Governed actions are written by database triggers into a hash-chained audit log — each row's hash covers the previous one, so a removed or edited entry breaks the chain. The chain can be verified independently of the database that produced it.

Retention and archive

Audit events have a configurable retention window with NDJSON archive export. Execution traces and swarm runs have their own retention setting, purged in bounded batches.

IAM, groups and model rules

Resources are shared through group grants with row filters and column masks. Which models an account may call is governed by allow-list rules.

Budgets and full traces

Every model call is recorded with user, model, token counts and cost. Monthly caps can be set per user and per group.

SAML SSO

Enterprise single sign-on is supported via your identity provider.

What we do not claim

The gaps, stated plainly. A security page that overstates is worse than none — this section is here so your reviewer finds the limits from us rather than from a surprise.

No third-party certification

AgentSwarms is not SOC 2, ISO 27001 or HIPAA certified. Because you self-host, the certified boundary in your architecture is your own infrastructure and your Supabase project — the compliance posture of the deployment is yours to assert, and we do not claim it for you.

No penetration-test report

There is no third-party penetration test to share. The source is available for your own review, which for many buyers is a stronger position than a summary letter.

The master key lives in your environment

PROVIDER_CREDS_SECRET is an environment variable you set and back up. There is no external KMS integration yet — sourcing it from AWS KMS, GCP KMS, Azure Key Vault, OCI Vault or HashiCorp Vault is designed in docs/KEY_MANAGEMENT.md and not built. Rotation itself is supported and operator-initiated: the app never rotates on a schedule by itself.

Encryption at rest is not end-to-end

The server decrypts credentials in order to use them, so a compromised server process can read them in memory. Encryption at rest protects a stolen database dump; it is not a defence against code running on your own host.

No hardware-backed key storage

Keys are derived in software from an environment variable. There is no HSM or secure-enclave path.

Reporting a vulnerability

Please report suspected vulnerabilities privately rather than opening a public issue. Use GitHub’s private security advisory on the repository, or the security contact in SECURITY.md. Tell us what you did, what you expected and what happened; a proof of concept helps. We will acknowledge, keep you updated while we investigate, and credit you when a fix ships unless you would rather we did not.

Self-hosting means most of these controls are ones you operate rather than ones we run for you. Deployment guidance, including the environment variables referenced here, is in docs/DEPLOYMENT.md.