Skip to content

Security: PersonaliAI/chatty

SECURITY.md

πŸ›‘οΈ Security Policy

Reporting a Vulnerability

Please do NOT open a public GitHub issue for security vulnerabilities.

Instead, use GitHub's built-in private vulnerability reporting:

  1. Go to the Security tab of this repository
  2. Click Report a vulnerability
  3. Fill in the details β€” the more context, the faster we can triage

Response Timeline

Stage Target
Initial acknowledgment 48 hours
Triage and severity assessment 7 days
Patch development Depends on severity β€” critical issues are prioritized immediately
Public disclosure 90 days after initial report, or sooner if a patch is released

We follow coordinated disclosure. We will not take legal action against researchers who report vulnerabilities responsibly.


Scope

In Scope

  • Authentication & authorization β€” Supabase Auth integration, JWT verification, RBAC (owner/admin/agent roles)
  • API security β€” All FastAPI endpoints under /api/
  • Widget origin verification β€” JWT-signed widget tokens (FUNCTION_SECRET)
  • MCP OAuth 2.0 server β€” Authorization code flow with PKCE (RFC 7636), dynamic client registration (RFC 7591), token issuance and verification
  • BYOK encryption β€” Fernet AES-128-CBC encryption of customer-supplied LLM API keys at rest
  • Data storage β€” Supabase PostgreSQL with Row-Level Security (RLS) policies
  • Webhook signature verification β€” HMAC-SHA256 for Lemon Squeezy, WhatsApp Cloud, Slack, and outbound webhooks
  • File upload validation β€” Multipart upload sanitization and Supabase Storage access controls
  • Outbound request filtering β€” SSRF firewall blocking RFC-1918 / loopback IP ranges for crawlers and webhooks

Out of Scope

  • Third-party managed services (Supabase, LLM providers, Lemon Squeezy) β€” report to those vendors directly
  • Social engineering attacks against project maintainers
  • Denial of service (DoS/DDoS)
  • Vulnerabilities in dependencies β€” report upstream; we monitor via Dependabot and pip-audit
  • Self-hosted deployment misconfigurations (e.g., exposed .env files, missing TLS)

Security Architecture

Authentication & Access Control

  • Supabase Auth handles user identity with JWT tokens verified server-side via deps.py
  • Row-Level Security (RLS) on all Supabase tables β€” the service_role key is only used server-side, never exposed to clients
  • Role-Based Access Control (RBAC) with three roles: owner (full access), admin (configurable tab permissions), agent (restricted to live inbox)
  • Widget origin tokens β€” cryptographic JWTs signed by FUNCTION_SECRET ensure widget embed calls originate from allowed domains

MCP OAuth 2.0 Server

  • Authorization Code with PKCE (RFC 7636) β€” mandatory code verifier/challenge for all MCP client authorization
  • Dynamic Client Registration (RFC 7591) β€” MCP clients self-register without pre-shared secrets
  • Authorization Server Metadata (RFC 8414) β€” auto-discoverable at /.well-known/oauth-authorization-server
  • Scoped access tokens β€” read, write, knowledge, actions, admin

Encryption

  • BYOK keys at rest β€” customer-supplied LLM API keys are encrypted with Fernet (AES-128-CBC) using BYOK_ENCRYPTION_KEY before storage; decrypted only at inference time in memory
  • OAuth state tokens β€” signed JWTs prevent CSRF in OAuth flows
  • Webhook signatures β€” all inbound webhooks are verified via HMAC-SHA256 before processing

Network Security

  • SSRF firewall (app/core/ssrf.py) β€” blocks outbound HTTP requests to private/reserved IP ranges (10.x, 172.16–31.x, 192.168.x, 127.x, ::1, link-local) for URL crawlers and webhook deliveries
  • Rate limiting β€” distributed fixed-window rate limiter via Upstash Redis REST API with automatic in-memory fallback
  • Security headers middleware β€” Content-Security-Policy, Strict-Transport-Security (HSTS), X-Content-Type-Options, X-Frame-Options
  • CORS β€” strict origin allowlist for dashboard; dynamic origin reflection for widget endpoints only
  • Request ID tracing β€” every request gets a unique X-Request-ID for audit trail correlation

Data Protection

  • PII scrubber (app/services/pii_service.py) β€” redacts credit card numbers, SSNs, and sensitive patterns before LLM inference
  • Conversation data sovereignty β€” all data stays in the customer's own Supabase project
  • No telemetry β€” self-hosted instances send zero data to PersonaliAI

Credential Management

Required Secrets

Secret Purpose Rotation Guidance
SUPABASE_SECRET_KEY Server-side Supabase access (bypasses RLS) Rotate via Supabase dashboard β†’ Settings β†’ API β†’ Regenerate
FUNCTION_SECRET Signs widget origin JWTs and OAuth state tokens Regenerate with python -c "import secrets; print(secrets.token_urlsafe(32))" β€” existing widget tokens will be invalidated
BYOK_ENCRYPTION_KEY Encrypts customer BYOK LLM keys at rest Generate with python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())" β€” rotating this invalidates all stored BYOK keys
GEMINI_API_KEY Default LLM provider Rotate via Google AI Studio

Storage Rules

  • Never commit a filled .env file β€” all .env files are gitignored
  • Use a secret manager (Vault, AWS Secrets Manager, GCP Secret Manager, Railway/Render built-in secrets) in production
  • OAuth client secrets (Google, Microsoft, Zoom) should be rotated annually

Dependency Management

Tool What it does Frequency
Dependabot (.github/dependabot.yml) Watches pip, npm, Docker, and GitHub Actions dependencies Weekly
pip-audit Scans Python dependencies for known CVEs in CI Every push/PR to main
CodeQL (.github/workflows/codeql.yml) Static analysis for common vulnerability patterns Every push/PR to main
Secret scanning (.github/workflows/secret-scan.yml) Detects accidentally committed secrets Every push/PR to main

Supported Versions

Version Supported
Latest main branch βœ… Active security updates
Older commits / tags ❌ No backports β€” update to latest

We do not maintain separate release branches. Security fixes are applied to main and released immediately.


Disclosure Policy

We follow coordinated disclosure:

  1. Reporter submits via GitHub's private vulnerability reporting
  2. We acknowledge within 48 hours and begin triage
  3. We develop and test a fix
  4. We release the patch and publish a GitHub Security Advisory
  5. The reporter is credited (unless they prefer anonymity)
  6. Full details are disclosed 90 days after the initial report, or immediately upon patch release β€” whichever comes first

We will never pursue legal action against security researchers acting in good faith.


Security Best Practices for Self-Hosters

  • Always deploy behind TLS (HTTPS) β€” use a reverse proxy like Caddy, nginx, or your platform's built-in TLS
  • Set CHATTY_BACKEND_URL and CHATTY_FRONTEND_URL to your real production domains
  • Use the session pooler or direct connection string for migrations, not the transaction pooler
  • Keep your Supabase service_role key strictly server-side β€” never expose it in frontend code or client-side configuration
  • Enable Supabase's built-in email confirmation for sign-ups in production
  • Review and restrict the allowed_domains list for each bot to prevent unauthorized widget embedding
  • Monitor docker compose logs and Sentry (if configured) for anomalous patterns

Questions about security? Open a discussion (for general questions) or use private vulnerability reporting (for vulnerabilities).

There aren't any published security advisories