package middleware import ( "strings" "github.com/gin-gonic/gin" ) const contentSecurityPolicy = "default-src 'none'; frame-ancestors 'none'; base-uri 'none'; form-action 'self'" func SecurityHeaders() gin.HandlerFunc { return func(c *gin.Context) { headers := c.Writer.Header() headers.Set("X-Content-Type-Options", "nosniff") headers.Set("X-Frame-Options", "DENY") headers.Set("Referrer-Policy", "strict-origin-when-cross-origin") headers.Set("Permissions-Policy", "camera=(), microphone=(), geolocation=()") headers.Set("Cross-Origin-Opener-Policy", "same-origin") headers.Set("X-Permitted-Cross-Domain-Policies", "none") if shouldAttachCSP(c.FullPath(), c.Request.URL.Path) { headers.Set("Content-Security-Policy", contentSecurityPolicy) } if isHTTPSRequest(c) { headers.Set("Strict-Transport-Security", "max-age=31536000; includeSubDomains") } c.Next() } } func shouldAttachCSP(routePath, requestPath string) bool { path := strings.TrimSpace(routePath) if path == "" { path = strings.TrimSpace(requestPath) } return !strings.HasPrefix(path, "/swagger/") } func isHTTPSRequest(c *gin.Context) bool { if c.Request.TLS != nil { return true } return strings.EqualFold(strings.TrimSpace(c.GetHeader("X-Forwarded-Proto")), "https") }