diff options
| author | Peter Stone <thepeterstone@gmail.com> | 2026-01-26 07:01:25 -1000 |
|---|---|---|
| committer | Peter Stone <thepeterstone@gmail.com> | 2026-01-26 07:01:25 -1000 |
| commit | 8c2c88f90039e87b29ce32cd31b7b0361b5803d0 (patch) | |
| tree | 6099e498084b876d343b071bbdf2cb62838eae7d /cmd/dashboard | |
| parent | f5b997bfc4c77ef262726d14b30d387eb7acd1c6 (diff) | |
Phase 1: Critical security fixes
- Remove default password fallback - require DEFAULT_PASS in all environments
- Fix XSS vulnerabilities in HTML generation (handlers.go:795,920)
- Add security headers middleware (X-Frame-Options, CSP, HSTS, etc.)
- Add rate limiting on login endpoint (5 req/15min per IP)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Diffstat (limited to 'cmd/dashboard')
| -rw-r--r-- | cmd/dashboard/main.go | 17 |
1 files changed, 9 insertions, 8 deletions
diff --git a/cmd/dashboard/main.go b/cmd/dashboard/main.go index 40a5002..d7da061 100644 --- a/cmd/dashboard/main.go +++ b/cmd/dashboard/main.go @@ -21,6 +21,7 @@ import ( "task-dashboard/internal/auth" "task-dashboard/internal/config" "task-dashboard/internal/handlers" + appmiddleware "task-dashboard/internal/middleware" "task-dashboard/internal/store" ) @@ -59,11 +60,7 @@ func main() { defaultUser = "admin" } if defaultPass == "" { - if !cfg.Debug { - log.Fatal("CRITICAL: DEFAULT_PASS must be set in production. Set DEBUG=true for development.") - } - log.Println("WARNING: Using default password - set DEFAULT_PASS for production") - defaultPass = "changeme" + log.Fatal("CRITICAL: DEFAULT_PASS environment variable must be set. Cannot start without a password.") } if err := authService.EnsureDefaultUser(defaultUser, defaultPass); err != nil { log.Printf("Warning: failed to ensure default user: %v", err) @@ -112,12 +109,16 @@ func main() { r.Use(middleware.Logger) r.Use(middleware.Recoverer) r.Use(middleware.Timeout(60 * time.Second)) - r.Use(sessionManager.LoadAndSave) // Session middleware must be applied globally - r.Use(authHandlers.Middleware().CSRFProtect) // CSRF protection + r.Use(appmiddleware.SecurityHeaders(cfg.Debug)) // Security headers + r.Use(sessionManager.LoadAndSave) // Session middleware must be applied globally + r.Use(authHandlers.Middleware().CSRFProtect) // CSRF protection + + // Rate limiter for auth endpoints (5 requests per 15 minutes per IP) + authRateLimiter := appmiddleware.NewRateLimiter(5, 15*time.Minute) // Public routes (no auth required) r.Get("/login", authHandlers.HandleLoginPage) - r.Post("/login", authHandlers.HandleLogin) + r.With(authRateLimiter.Limit).Post("/login", authHandlers.HandleLogin) r.Post("/logout", authHandlers.HandleLogout) // Serve static files (public) |
