If you discover a security vulnerability, please report it through GitHub Security Advisories. Do not open a public issue for security vulnerabilities.
We will acknowledge reports within 48 hours and provide a timeline for fixes.
| Feature | Implementation |
|---|---|
| Password storage | bcrypt (legacy PBKDF2-SHA256 hashes are verified and auto-rehashed on login) |
| Password policy | Minimum 8 characters with at least 1 uppercase letter and 1 digit (enforced via Pydantic schema validation) |
| Authentication | httpOnly cookie (JWT HS256), Bearer token fallback for API testing |
| Rate limiting | 10/min for registration, 20/min for login (slowapi) |
| CORS | Restricted to localhost, 127.0.0.1, and 192.168.x.x via regex |
| Data isolation | All queries filtered by family_id with membership verification |
| Docker containers | Frontend runs as tribu; backend creates tribu and drops privileges with gosu when supported |
| Docker networking | PostgreSQL and Valkey are not exposed to the host and stay inside the Docker network |
| Build process | Multi-stage frontend build, .dockerignore files for both services |
| CSV import | Row limit (500), range checks on month/day fields, email format validation |
The backend will refuse to start without these variables set:
JWT_SECRET: Used for signing authentication tokens. Generate withopenssl rand -hex 32.DATABASE_URL: PostgreSQL connection string. In Docker Compose, this is constructed fromPOSTGRES_PASSWORD.POSTGRES_PASSWORD: Database password. Generate withopenssl rand -hex 16.
Never use default or placeholder values for these secrets.
- Copy
docker/.env.exampletodocker/.envand generate strong secrets - If exposing Tribu to the internet, put it behind a reverse proxy (nginx, Caddy, Traefik) with TLS
- Keep Docker images up to date for security patches
Feature work that touches authentication, integrations, exports, backups, self-hosted deployment, or shared-device surfaces should use the Defensive review checklist. It gives maintainers a public-safe boundary checklist, links existing coverage, and explains when to create narrow follow-up issues.
Follow these steps before exposing Tribu to the internet:
- TLS termination: Place Tribu behind a reverse proxy (Caddy, nginx, or Traefik) with a valid TLS certificate. Caddy handles this automatically with Let's Encrypt.
- Enable secure cookies: Set
SECURE_COOKIES=truein your.envfile. This adds theSecureflag to auth cookies so they are only sent over HTTPS. - Generate strong secrets: Use
openssl rand -hex 32forJWT_SECRETandopenssl rand -hex 16forPOSTGRES_PASSWORD. Never reuse secrets across instances. - Restrict CORS (optional): The default regex allows all
192.168.x.xaddresses. If your instance is public, consider narrowing this to your specific domain by modifying theallow_origin_regexinbackend/app/main.py. - Backups: Schedule regular PostgreSQL backups and test restore procedures. The Backup & Restore guide documents the supported operations flow.
- Keep images updated: Rebuild Docker images periodically to pick up security patches in base images and dependencies.
| Limitation | Context |
|---|---|
| No HTTPS in dev | Cookies use secure=false for local development. Set SECURE_COOKIES=true in .env when behind TLS. |
| No CSRF token | SameSite=Lax mitigates common cross-origin form submissions. Reassess if cross-site or embedded use cases are added. |
| No email verification | Registration does not require email confirmation. |
| No account lockout | Failed login attempts are rate-limited but do not lock accounts. |
The frontend image runs as the dedicated non-root tribu user. The backend image creates the same user and the entrypoint drops privileges with gosu when the runtime supports it; in constrained environments where gosu is unavailable, the backend logs that it is running as root. The Docker Compose configuration does not expose database or cache ports to the host, keeping PostgreSQL and Valkey accessible only within the Docker network.
Build artifacts are minimized through:
- Multi-stage builds for the frontend (build step separated from runtime)
.dockerignorefiles excluding development files, git history, and documentation from images