Strip detailed security internals from README
Reduces the security section to a brief summary without exposing specific middleware names, rate limit thresholds, lockout parameters, or implementation details that could aid threat actors. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
2848739474
commit
7903e454dc
32
README.md
32
README.md
@ -110,29 +110,7 @@ A self-hosted, multi-user life administration app with a dark-themed UI and role
|
||||
|
||||
## Security
|
||||
|
||||
### Hardened by default
|
||||
|
||||
- **Multi-user data isolation** — all resources scoped by `user_id` with per-query filtering; pentest-verified (51+ test cases, 0 exploitable IDOR findings)
|
||||
- **Role-based access control** — `admin` and `standard` roles with `require_admin` dependency on all admin endpoints
|
||||
- **CSRF protection** — global `CSRFHeaderMiddleware` requires `X-Requested-With: XMLHttpRequest` on all mutating requests
|
||||
- **Input validation** — `extra="forbid"` on all Pydantic schemas prevents mass-assignment; `max_length` on all string fields; `ge=1, le=2147483647` on path IDs
|
||||
- **Non-root containers** — both backend (`appuser:1000`) and frontend (`nginx-unprivileged`) run as non-root
|
||||
- **No external backend port** — port 8000 is internal-only; all traffic flows through nginx
|
||||
- **Server version suppression** — `server_tokens off` (nginx) and `--no-server-header` (uvicorn)
|
||||
- **Rate limiting** — nginx `limit_req_zone` (10 req/min) on `/api/auth/login` (burst=5), `/verify-password` (burst=5), `/change-password` (burst=5), `/totp-verify` (burst=5), `/setup` (burst=3)
|
||||
- **DB-backed account lockout** — 10 failed attempts triggers 30-minute lock per account
|
||||
- **Inactive user blocking** — disabled accounts rejected at login (HTTP 403) without session creation, lockout reset, or last_login_at update
|
||||
- **Timing-safe login** — dummy Argon2id hash for non-existent users prevents username enumeration
|
||||
- **Password reuse prevention** — change-password endpoint rejects same password as old
|
||||
- **Dotfile blocking** — `/.env`, `/.git/config`, etc. return 404 (`.well-known` preserved for ACME)
|
||||
- **CSP headers** — Content-Security-Policy on all responses, scoped for Google Fonts
|
||||
- **CORS** — configurable origins with explicit method/header allowlists
|
||||
- **API docs disabled in production** — Swagger/ReDoc/OpenAPI only available when `ENVIRONMENT=development`
|
||||
- **Argon2id password hashing** with transparent bcrypt migration on first login
|
||||
- **DB-backed sessions** — revocable, with signed itsdangerous httpOnly cookies, 7-day sliding window with 30-day hard ceiling
|
||||
- **Optional TOTP MFA** — authenticator app support with backup codes, admin-enforced MFA for new users
|
||||
- **Invited editor field allowlist** — can_modify invitees restricted to content fields only (title, description, time, color, location); calendar moves, recurring series changes, and deletions blocked server-side
|
||||
- **5 penetration tests passed** — RBAC, header hardening, SSRF, shared calendars, event invitations; 0 exploitable findings
|
||||
UMBRA is hardened by default with multi-user data isolation, role-based access control, CSRF protection, non-root containers, rate limiting, account lockout, optional TOTP MFA, and secure session management. Multiple penetration tests have been conducted with no exploitable findings.
|
||||
|
||||
### Production Hardening
|
||||
|
||||
@ -141,21 +119,15 @@ Before deploying to production, generate secure values for your `.env`:
|
||||
```bash
|
||||
# Generate a secure SECRET_KEY (64-char hex string)
|
||||
python3 -c "import secrets; print(secrets.token_hex(32))"
|
||||
# or: openssl rand -hex 32
|
||||
|
||||
# Generate a secure database password
|
||||
python3 -c "import secrets; print(secrets.token_urlsafe(24))"
|
||||
# or: openssl rand -base64 24
|
||||
|
||||
# Set ENVIRONMENT to disable Swagger/ReDoc and auto-enable secure cookies
|
||||
ENVIRONMENT=production
|
||||
```
|
||||
|
||||
Additionally for production:
|
||||
- Set `ENVIRONMENT=production` — disables API docs and auto-enables HTTPS-only session cookies
|
||||
- Place behind a reverse proxy with TLS termination (e.g., Caddy, Traefik, or nginx with Let's Encrypt)
|
||||
- Set `ENVIRONMENT=production` — this disables API docs and auto-enables HTTPS-only session cookies (`COOKIE_SECURE` derives from `ENVIRONMENT`; override with `COOKIE_SECURE=false` if running non-TLS prod behind a proxy)
|
||||
- Set `CORS_ORIGINS` to your actual domain (e.g., `https://umbra.example.com`)
|
||||
- Consider adding HSTS headers at the TLS-terminating proxy layer
|
||||
|
||||
## API Overview
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user