diff --git a/internal/handlers/admin/routes.go b/internal/handlers/admin/routes.go index 0d8d0cd..d214d15 100644 --- a/internal/handlers/admin/routes.go +++ b/internal/handlers/admin/routes.go @@ -29,6 +29,7 @@ func NewRouter(deps Dependencies) *gin.Engine { r.Use(middleware.RequestID) r.Use(middleware.Logging) r.Use(middleware.Recovery) + r.Use(middleware.SecurityHeaders(strings.HasPrefix(deps.Config.BaseURL, "https"))) tsAuth := &TailscaleAuth{allowedUsers: deps.Config.TailscaleAllowedUsers} r.Use(tsAuth.Middleware) diff --git a/internal/handlers/public/routes.go b/internal/handlers/public/routes.go index 1aa6cc7..f704936 100644 --- a/internal/handlers/public/routes.go +++ b/internal/handlers/public/routes.go @@ -31,6 +31,7 @@ func NewRouter(deps Dependencies) *gin.Engine { r.Use(middleware.RequestID) r.Use(middleware.Logging) r.Use(middleware.Recovery) + r.Use(middleware.SecurityHeaders(strings.HasPrefix(deps.Config.BaseURL, "https"))) r.Use(deps.Auth.SessionMiddleware) csrfSecret := []byte(deps.Config.SessionSecret) diff --git a/internal/middleware/middleware.go b/internal/middleware/middleware.go index 7fc3d03..48378a1 100644 --- a/internal/middleware/middleware.go +++ b/internal/middleware/middleware.go @@ -44,3 +44,15 @@ func Recovery(c *gin.Context) { }() c.Next() } + +func SecurityHeaders(secure bool) gin.HandlerFunc { + return func(c *gin.Context) { + c.Header("X-Content-Type-Options", "nosniff") + c.Header("X-Frame-Options", "DENY") + c.Header("Referrer-Policy", "strict-origin-when-cross-origin") + if secure { + c.Header("Strict-Transport-Security", "max-age=63072000; includeSubDomains") + } + c.Next() + } +}