Security¶
BillTracker is self-hosted. The application provides security controls, and the operator remains responsible for HTTPS, host access, volume protection, and updates.
How does authentication work?¶
- Local passwords are hashed with bcrypt.
- Successful login creates a random server-side session with a 7-day expiry.
- The
bt_sessionbrowser cookie is HTTP-only and SameSitestrict. - Password resets, role changes, and account deactivation invalidate sessions.
- The bootstrap admin is blocked from user tracker routes.
- Optional OIDC uses PKCE, state, nonce, provider discovery, and token validation.
- TOTP and WebAuthn are available as second factors; see Profile and Login Privacy.
Who can access what?¶
User-data routes require authentication and derive ownership from the active
session. Admin routes require the admin role. Single-user mode may attach one
configured regular user without login, but it does not grant access to admin
routes.
How is CSRF protected?¶
Mutating API requests use a double-submit CSRF token:
- The server sets
bt_csrf_token(httpOnly by default since v0.35). - The SPA fetches the token from
GET /api/auth/csrf-tokenon startup and stores it in an in-memory module cache. - The SPA sends the value in
x-csrf-token. - The server rejects a missing or mismatched token.
The httpOnly default removes the token from the XSS-accessible cookie
surface. Set CSRF_HTTP_ONLY=false only for a custom client that needs
document.cookie access. See Tune Security Settings
for the full knob list.
What rate limits apply?¶
| Operation | Limit |
|---|---|
| Login | 10 per 15 minutes per IP |
| Password changes | 5 per 15 minutes per IP |
| SimpleFIN sync and backfill | 10 per 15 minutes per user (since v0.37; keyed by user ID, not IP) |
| Imports | 20 per 15 minutes per IP |
| Exports | 30 per 15 minutes per IP |
| Admin actions | 30 per 15 minutes per IP |
| OIDC requests | 20 per 15 minutes per IP |
| Backup operations | 5 per 60 minutes per IP |
| Demo-data clear | 3 per 15 minutes per IP |
What response headers does the server send?¶
The server sends:
- A nonce-based Content Security Policy
X-Content-Type-Options: nosniffX-Frame-Options: SAMEORIGINReferrer-Policy: strict-origin-when-cross-originX-Permitted-Cross-Domain-Policies: none- HSTS when
HTTPS=true
How is sensitive data protected?¶
- SQLite and backup files are not served as static files.
- SimpleFIN access URLs, SMTP passwords, OIDC client secrets, TOTP secrets and recovery codes, push notification tokens, and login-history IP/UA/location columns are encrypted at rest with AES-256-GCM (HKDF-SHA-256).
- Sessions are stored as
SHA-256(token)(since v0.37) — the raw token lives only in the browser cookie. - IP geolocation is a per-user opt-in from Profile → Privacy. When disabled,
no outbound
ip-api.comcall is made for that user's login andlocation_*columns inuser_login_historyare left null for new entries. - Sync, backfill, and password-change endpoints are rate-limited per user.
- Backup restore validates managed paths and creates a pre-restore snapshot.
- Import flows separate preview from apply and validate uploaded content.
- Sensitive administrative actions are recorded in
audit_log.
What should I do before exposing the app?¶
- Use HTTPS and verify cookie flags behind your reverse proxy.
- Keep
/datareadable only by trusted operators. - Remove or rotate bootstrap passwords after first setup.
- Back up the database before upgrades.
- Keep the image and host patched.
- Protect backup downloads and exports; BillTracker does not encrypt those files.
The Calendar Feed URL is a bearer credential; treat it like a password and regenerate it on suspicion of exposure.
See also¶
- Tune Security Settings — CSRF, cookies, HTTPS, and token-encryption knobs
- Profile and Login Privacy — user login geolocation, login history, and WebAuthn enrollment
- Tune Security Settings — encryption key separation and deployment security knobs
- Known Limitations — what BillTracker does not yet encrypt or proxy
- Operations Runbook — incident response
Next steps¶
- Tune the security knobs in Tune Security Settings.
- Put the app behind HTTPS with Reverse Proxy and HTTPS.
- Review login privacy in Profile and Login Privacy.
- Plan a deployment with the Operations Runbook.