Sparrow
Security
Sparrow holds conversations between businesses and their customers. This page describes the controls we actually operate — what we do, not what we aspire to.
Last updated 4 September 2026
What we do not claim
Sparrow does not hold SOC 2, ISO 27001, PCI DSS or HIPAA certification, and we make no formal compliance claims. Everything below is a control we run, described plainly so you can judge it for yourself.
Tenant isolation
Every workspace’s data is separated in the database itself, using PostgreSQL row-level security. Access is decided by policies attached to each table, evaluated by the database on every query — not by application code that could be bypassed by a bug in a single endpoint.
The identifiers that connect a business to WhatsApp are constrained the same way:
- A WhatsApp Business Account can belong to exactly one Sparrow workspace, enforced by a unique index.
- A business phone number can belong to exactly one Sparrow workspace, enforced the same way.
- A workspace may hold one live WhatsApp connection at a time, so there is never ambiguity about which account is being used.
- Inbound messages are attributed by looking their phone number up in that index — the tenant is derived from the database, never from anything in the request.
We maintain an automated suite that tries to breach these boundaries — reading another tenant’s rows, binding one WhatsApp account to two workspaces, sending as another organization — and it runs against the real database rather than a mock.
Role-based access
Members of a workspace hold one of five roles: owner, admin, marketer, agent or viewer. Roles are enforced by the same database policies that enforce isolation, so a viewer cannot send a message or change a connection even if a request is crafted by hand.
Managing the WhatsApp connection — connecting, reconnecting, disconnecting — is restricted to owners and admins.
How credentials are held
When a business connects WhatsApp, Meta issues Sparrow a credential that lets us act for that business. That credential is the most sensitive thing we hold, and it is treated accordingly.
Encrypted, in a dedicated store
Credentials are held in Supabase Vault, which encrypts them at rest with a key kept outside the database. A copy of the database does not yield a usable credential. They are never written to an ordinary table column.
Server-side only
The store is unreachable from the browser and from any signed-in user role — those roles are denied access at the schema level, not merely filtered by a policy. Only server-side processes can read a credential, and only through narrow functions that take a Sparrow connection identifier and verify it belongs to the organization asking.
Never displayed, never logged, never returned
No Sparrow screen shows an access token. No API response contains one. Our logging is written so that a credential cannot appear in it, and we test for that.
Rotated and revocable
Reconnecting replaces the stored credential in place. Disconnecting deletes it outright — not marked unused, deleted — which stops all sending immediately.
Application secrets — our Meta app secret, database service keys, provider API keys — live only in server environment configuration. They are never stored in the database and never shipped to the browser.
Webhook validation
Meta delivers messages to Sparrow over a public endpoint, so the signature on each delivery is the entire trust boundary. Every request is verified with an HMAC computed over the exact raw bytes received, compared in constant time. Nothing touches the database until that check passes; a missing, malformed or incorrect signature is rejected identically.
Deliveries are also de-duplicated, so Meta’s automatic retries cannot cause a message to be processed or delivered twice.
Transport security
Sparrow is served over HTTPS only, with HTTP redirected. Connections to Meta, to our database and to every service provider are made over TLS. The application runs on managed infrastructure with platform-level patching.
Least privilege
Server processes use the narrowest credential that will do the job. Reads that can be made as the signed-in user are made as the signed-in user, so that row-level security applies; the elevated database role is used only where there is no user session at all, such as processing an inbound webhook.
From Meta we request exactly two permissions — whatsapp_business_management and whatsapp_business_messaging — and nothing else. We do not request access to business portfolios, ad accounts, catalogs, Pages or Instagram accounts.
Logging and auditability
We keep operational records that let us investigate problems and abuse: authentication events, webhook deliveries and their outcomes, message send attempts and their results, and errors. Every inbound webhook is recorded with the outcome of processing it, including deliveries we could not attribute to any workspace — those are retained with no organization attached, so they are visible to no tenant.
Within the product, actions that change a workspace — invitations, role changes, connection changes — are attributable to the member who made them.
Deletion
Disconnecting WhatsApp deletes the stored credential immediately and stops sending, while leaving conversations and contacts intact. Workspace and account deletion are handled on request, with limited retention where law, tax, security or abuse-prevention requires it.
The full process is on our data deletion page.
Subprocessors
Sparrow runs on services operated by others, under contract and only to deliver the service. The current set is listed on our integrations page, alongside what each one does. It is not a permanent list, and we update that page when it changes.
Reporting a problem
If you believe you have found a vulnerability in Sparrow, tell us before disclosing it publicly and we will work with you on it. Please include enough detail to reproduce the issue. We do not currently run a paid bug bounty.
Contact
Email hello@sparrow.qa. Sparrow is operated by The Sketch Agency for Designs.