Security
How we protect your data
Last updated: 2026-05-24
Security is a first-class concern. This page describes the controls in place and how to report vulnerabilities.
Authentication
- Passwords hashed with bcrypt (cost factor 12) — never stored in plaintext
- Two-factor authentication: TOTP (Authenticator app, RFC 6238) and SMS OTP
- JWT session tokens with per-device
jtitracking — individual sessions revocable from Settings → Active devices - Account lockout: 10 failed login attempts within 1 hour triggers a 30-minute cooldown
- Social login: Google + Apple OAuth with HMAC-signed CSRF state nonces
- OTP codes use cryptographic
secrets.randbelow, comparison viahmac.compare_digest(timing-safe)
Transport & storage
- TLS 1.3 enforced on all endpoints (Let's Encrypt certificates, auto-renewing)
- HTTP → HTTPS redirect on every request
- Database (SQLite + WAL) on encrypted EBS volume in AWS Singapore
- Daily snapshots retained 30 days
Email authentication
- DKIM — domain-keys signed via AWS SES (RSA-2048)
- SPF —
v=spf1 include:amazonses.com -all - DMARC — published with
ruareporting to postmaster@tylellm.com
Payments
- PCI-DSS compliance via Stripe — we never see or store card numbers
- Webhook signature verification on every Stripe callback
- Idempotency keys prevent double-charges on PaymentIntent creation
Application controls
- Rate limiting: per-IP and per-user, with burst-tolerant token buckets
- Avatar uploads: magic-byte verification rejects spoofed file types
- Password reset: 6-digit OTP, 15-minute TTL, revokes all existing sessions on completion
- New-device login: alert email sent on first sign-in from an unseen IP+browser combination
- OAuth state CSRF: every social login round-trip carries an HMAC-signed nonce
Organization workspace controls (Organization plan)
- Role-based access — Owner / Admin / Member roles enforced server-side on every endpoint. Resource queries scope by
X-Organization-Idheader verified againstorg_memberstable; non-members get 403. - Per-chat share scope — chats default to
private; only the author can flip toorg. Backend GET filters every list query by(user_id == me) OR (share_scope == 'org' AND org_id == header). - Anti-duplicate guard —
POST /auth/sessionsrejects with 409 Conflict any insert whose client-minted UUID is already owned by another user, blocking cross-user chat hijack via stale clients. - Append-only audit log —
org_audit_logsrecords every share / edit / delete / role-change / billing event with actor, role-snapshot, IP, and detail JSON. No update / delete API exposed. - Real-time channel auth — Server-Sent Events endpoint (
/auth/sessions/stream) requires a signed JWT and verifies workspace membership before subscribing; events are fan-out only to the requested org's queue. - Invite tokens — 64-byte URL-safe random, single-use, 14-day TTL, revokable. Accept flow verifies email match before granting membership.
Privacy
- Conversations not used for AI training unless you explicitly opt in (Settings → Privacy)
- Account deletion is hard-delete within 30 days — see Privacy Policy
- Export everything you've shared with us: Settings → Data → "Download account data"
Responsible disclosure
Found a vulnerability? Please email security@tylellm.com. Include:
- A description of the issue and impact
- Step-by-step reproduction
- Any relevant URLs, payloads, or screenshots
Please do not:
- Publicly disclose before we've had a chance to fix (we aim to triage within 72 hours)
- Access data belonging to other users beyond what's needed to demonstrate the issue
- Run automated scanners against production without prior coordination
We don't run a paid bug bounty yet, but we acknowledge reports publicly (with your permission) and credit researchers in our changelog.
Out of scope
- Reports from automated scanners without proof-of-impact
- Missing security headers without demonstrable exploit
- Self-XSS or issues requiring social engineering
- Rate-limit / DoS testing
Contact
Security: security@tylellm.com · PGP key on request.