Security

Security at Karibu

We hold a Gmail OAuth token and an Anthropic API key from every customer. Our entire business depends on never abusing either. Here's how we engineer that.

Encryption at rest

OAuth tokens (Gmail, Outlook), SMTP passwords, and API tokens are encrypted with AES-GCM (256-bit key, 96-bit IV per record) via Postgres pgcrypto before they land on disk. The encryption key lives in Vercel + Railway secrets and is rotated on a documented schedule; it never sits in the repo. Decryption happens only at the moment of use, inside a worker process, and the plaintext value is never logged, never serialised into application logs, and never returned to the browser.

Encryption in transit

Every connection that carries customer data is TLS 1.2+ end-to-end: browser ↔ Vercel, Vercel ↔ Supabase, workers ↔ Supabase, workers ↔ payment providers, workers ↔ email providers, and webhooks back in. HTTP requests to usekaribu.com are automatically upgraded to HTTPS at the edge, and HSTS is preloaded so downgrade attacks aren't reachable from a fresh browser either.

Access controls — RLS + four-tier role hierarchy

Customer access is governed by a four-tier role model: owner (full workspace control, billing, deletion), member (day-to-day work), admin (Karibu-side platform admin — separate from your workspace), and staff (Karibu support, scoped per-incident). Every row in every table is filtered by workspace_id at the Postgres layer via row-level security — so even a buggy query in our own code can't return another workspace's data. Karibu staff cannot view customer data without an explicit, logged elevation event.

Tenant isolation via Postgres RLS

Every Karibu table that holds customer data has row-level security enabled and scoped by workspace_id. Cross-workspace reads are physically impossible at the database layer — not "shouldn't happen", but cannot happen. Service-role queries (workers, webhook handlers) bypass RLS deliberately and apply tenant scoping in code.

OAuth scope discipline

We request the minimum Gmail OAuth scopes we need: gmail.send for outbound and gmail.readonly for reply detection. We deliberately do NOT requestgmail.modify — we cannot move messages between folders, delete anything, or change your settings. Many lead-gen tools take the kitchen-sink scope. We don't.

Audit logging

Every credential access is logged to credential_access_log with the caller, purpose, and timestamp. Every meaningful action (workspace created, mailbox connected, contact marked bad, subscription cancelled) is logged to audit_log. Both tables are append-only and retained for 90 days (free tier) or 1 year (paid).

Webhook verification

Inbound webhooks from Pesapal, Flutterwave, Gmail Pub/Sub, and others are verified via signature or shared-secret header. Bodies are never trusted on their own — for payments, we re-fetch authoritative status from the provider API before updating subscription state.

LinkedIn — no central storage

The Chrome extension reads what's on the LinkedIn page you're already viewing, in your own session. We never scrape LinkedIn at scale. We never store LinkedIn HTML or page content centrally. Activity logs capture metadata only (URL path, action, contact_id, timestamp) — never the agent's profile data.

Vulnerability disclosure

Found a security issue? Email security@usekaribu.com (PGP key on request). We respond within 1 business day. We don't pay bounties yet (small team), but we do credit responsible disclosure on this page and ship fixes fast.

Backups + disaster recovery

Supabase runs nightly full backups of the primary Postgres instance, retained for 7 days on the current plan and 30 days as we scale. Point-in-time recovery (PITR) is enabled, so we can restore the database to any second within the retention window — not just last night's snapshot. We additionally export to Supabase Storage weekly (retained 12 weeks) for an off-Supabase belt-and-braces copy. Recovery target: under 2 hours for the database, under 1 hour for the web tier. We restore-test quarterly.

Incident response

When we detect or are notified of a security incident, an internal triage starts immediately. We commit to disclosing any confirmed breach affecting customer data within 24 hours of confirmation — via email to every affected workspace owner, with what happened, what data was involved, what we've done, and what you should do. We also publish a redacted postmortem within 7 days for transparency. The 24-hour window is shorter than the 72-hour GDPR requirement on purpose: surprise is the enemy.

Data residency

Customer data — Postgres, file storage, backups — is hosted in the EU (Supabase Frankfurt, eu-central-1) region. Inference traffic to Anthropic also routes to EU endpoints where available. If you require a non-EU region (US, AU, etc.), talk to us — we'll spin a dedicated region project when revenue justifies it.

PII handling for prospect contact data

Karibu's job is to help you reach travel agents and DMCs, which means we handle their contact data on your behalf. Prospect names, emails, phone numbers, LinkedIn URLs, agency URLs, and the AI-generated intel briefs we produce about them are all tenant-scoped customer data — they live in the same workspace partition as everything else and inherit the same RLS, encryption, and access controls. We do not sell or share prospect data between workspaces. Bounced or invalid contacts can be marked bad, and prospects can request removal via privacy@usekaribu.com — we honour deletion requests across every workspace within 30 days.

Vendors / sub-processors

We use the following sub-processors to deliver the service. Each one is bound by a DPA or equivalent contract.

  • Vercel — web app hosting (US-edge, EU-edge routing).
  • Supabase — Postgres, Auth, Storage (EU Frankfurt).
  • Anthropic — AI inference for intel briefs and drafts.
  • Apify — actor-based public-source enrichment.
  • Pesapal — mobile-money and card payments (UG, KE).
  • Flutterwave — rest-of-Africa payments + USD.
  • Meta Cloud API — WhatsApp Business outbound (BSP-free).
We give 30 days notice before adding or changing any sub-processor. You can subscribe to the changelog at /legal/subprocessors.

What we don't have yet

We don't currently have SOC 2 Type II. We're early — that audit costs $30k+ and we'd rather spend it on shipping for the first 50 customers. Most enterprise procurement teams aren't where we sell. If you're a buyer who needs SOC 2, talk to us — we may have completed the certification by the time you're ready, and we'll prioritize it once a customer materially needs it.

Security questions before signing up?

Email security@usekaribu.com. The founder reads them. Most questions get answered within 24 hours.