5.4 KiB
Security Status
Last Audit: 2025-12-31 Target Users: Self-hosters, small businesses
Beta Release Criteria: See beta-checklist.md for overall release readiness assessment.
This document demonstrates our proactive approach to security through systematic vulnerability tracking and remediation.
Summary
| Phase | Status | Description |
|---|---|---|
| Phase 1-2 | ✅ Complete | Rate limiting, security headers, tests |
| Phase 3 | ✅ Complete | Critical fixes (token DoS, plaintext storage, fail-open) |
| Phase 4 | ✅ Complete | High priority (PKCE, WebAuthn, email re-auth, TOTP encryption) |
| Phase 5 | 🟡 In Progress | Security enhancements |
| Phase 6 | ⏳ Optional | Hardening & documentation |
Outstanding Security Issues
MEDIUM - Account Lockout Mechanism
Files: app/controllers/sessions_controller.rb, app/models/user.rb
Impact: Brute force attack mitigation
Implementation:
- Add
failed_login_attemptsandlocked_untilcolumns to users - Progressive delays: 5 attempts → 5s, 10 → 1min, 15 → 15min, 20+ → 1hr
- Admin notification on lockout
- Configurable via
MAX_LOGIN_ATTEMPTSENV
MEDIUM - Per-Account Rate Limiting
Files: app/controllers/sessions_controller.rb, config/initializers/rack_attack.rb
Impact: Distributed brute force prevention
Current: Global rate limiting only Needed: Add per-email rate limiting (10 failed attempts/email/hour)
LOW - WebAuthn Clone Detection Action
File: app/controllers/sessions_controller.rb:252-256
Impact: Cloned credential detection
Current: Logs warning on suspicious sign count Improvement: Block authentication, notify user/admin
Configuration Choices (Not Vulnerabilities)
These are policy decisions for self-hosters, not security bugs:
| Item | Default | Notes |
|---|---|---|
| Session cookie domain | Root domain | Enables SSO across subdomains. Add SECURE_SUBDOMAIN_ISOLATION ENV to disable |
| CSP policy | unsafe-inline, unsafe-eval | Required for Stimulus/Turbo. Audit JS to remove if needed |
| Logout redirect validation | Allows query params | Per OAuth 2.0 spec. Document behavior |
| Invitation token lifetime | 24 hours | Add INVITATION_TOKEN_LIFETIME ENV for high-security deployments |
| Password minimum length | 8 chars | Add PASSWORD_MIN_LENGTH ENV, consider zxcvbn |
| Admin self-demotion check | String comparison | Minor - use .to_i for integer comparison |
Completed Fixes
Phase 3 - Critical (December 2025)
1. Token Lookup DoS ✅
- Problem: O(n) BCrypt comparisons on token lookup
- Solution: HMAC-based token prefix for O(1) indexed lookup
- Files:
token_prefixable.rb, token models, migration
2. Plaintext Token Storage ✅
- Problem: Access tokens stored in plaintext
- Solution: Removed
tokencolumn, use BCrypt digest only - Files: Migration, fixtures, tests
3. Forward Auth Fail-Open ✅
- Problem: Unmatched domains allowed by default
- Solution: Changed to fail-closed (403 for unconfigured domains)
- Files:
forward_auth_controller.rb
Phase 4 - High Priority (December 2025)
4. PKCE Enforcement ✅
- Problem: PKCE was optional
- Solution: Per-app PKCE with mandatory enforcement for public clients
- Files: Application model, OIDC controller, migration
5. WebAuthn Info Disclosure ✅
- Problem:
/webauthn/checkleaked user_id and preferred_method - Solution: Minimal response, rate limiting (10/min), identical responses for non-existent users
- Files:
webauthn_controller.rb
6. OIDC State URL Encoding ✅
- Problem: State parameter not consistently URL-encoded
- Solution:
CGI.escape()on all redirect URLs - Files:
oidc_controller.rb(4 locations)
7. Email Change Re-authentication ✅
- Problem: Email could be changed without password
- Solution: Require current password for email changes
- Files:
profiles_controller.rb, view
12. TOTP Secret Encryption ✅
- Problem: TOTP secrets stored in plaintext
- Solution: Rails
encryptswith keys derived from SECRET_KEY_BASE - Files:
user.rb,active_record_encryption.rb
13. WebAuthn Credential ID Enumeration ✅
- Problem: Global credential lookup allowed enumeration via 404 vs 403 responses
- Solution: Scoped credential lookup to current user, identical responses
- Files:
webauthn_controller.rb,webauthn_credential_enumeration_test.rb
Security Strengths
- Token security: HMAC prefix + BCrypt, no plaintext storage
- Authorization codes: Pessimistic locking, single-use enforcement
- Refresh tokens: Family tracking for rotation attack detection
- Reserved claims: Validation prevents claim override attacks
- Rate limiting: Applied on all authentication endpoints
- Forward auth: Fail-closed by default
- TOTP: AES-256-GCM encryption at rest
- Email changes: Require password re-authentication
- Credential isolation: Scoped lookups prevent enumeration attacks
Audit History
| Date | Event |
|---|---|
| 2025-12-31 | Credential ID enumeration fix (scoped lookups) |
| 2025-12-31 | Security review - 1 new issue found (credential enumeration) |
| 2025-12-31 | Phase 4 completed (PKCE, WebAuthn, email re-auth, TOTP) |
| 2025-12-30 | Phase 3 completed (token DoS, plaintext storage, fail-open) |
| 2025-12-30 | Comprehensive security audit - 18 issues identified |
| Earlier | Phase 1-2 completed (rate limiting, headers, tests) |