package middleware import ( "github.com/gin-gonic/gin" ) // SecurityConfig holds configuration for security headers middleware type SecurityConfig struct { // EnableHSTS enables HTTP Strict Transport Security header EnableHSTS bool // HSTSMaxAge is the max-age value for HSTS in seconds (default: 31536000 = 1 year) HSTSMaxAge int // EnableNoSniff enables X-Content-Type-Options: nosniff EnableNoSniff bool // EnableXSSFilter enables X-XSS-Protection header EnableXSSFilter bool // EnableFrameDeny enables X-Frame-Options: DENY EnableFrameDeny bool // ContentSecurityPolicy sets the Content-Security-Policy header ContentSecurityPolicy string // ReferrerPolicy sets the Referrer-Policy header ReferrerPolicy string } // DefaultSecurityConfig returns a secure default configuration func DefaultSecurityConfig() SecurityConfig { return SecurityConfig{ EnableHSTS: true, HSTSMaxAge: 31536000, // 1 year EnableNoSniff: true, EnableXSSFilter: true, EnableFrameDeny: true, ContentSecurityPolicy: "default-src 'self'", ReferrerPolicy: "strict-origin-when-cross-origin", } } // SecurityHeaders creates a middleware that adds security headers to responses func SecurityHeaders(config SecurityConfig) gin.HandlerFunc { return func(c *gin.Context) { // Prevent MIME type sniffing if config.EnableNoSniff { c.Header("X-Content-Type-Options", "nosniff") } // XSS protection (legacy, but still useful for older browsers) if config.EnableXSSFilter { c.Header("X-XSS-Protection", "1; mode=block") } // Prevent clickjacking if config.EnableFrameDeny { c.Header("X-Frame-Options", "DENY") } // HTTP Strict Transport Security if config.EnableHSTS { hstsValue := "max-age=31536000; includeSubDomains" if config.HSTSMaxAge > 0 { hstsValue = "max-age=" + string(rune(config.HSTSMaxAge)) + "; includeSubDomains" } c.Header("Strict-Transport-Security", hstsValue) } // Content Security Policy if config.ContentSecurityPolicy != "" { c.Header("Content-Security-Policy", config.ContentSecurityPolicy) } // Referrer Policy if config.ReferrerPolicy != "" { c.Header("Referrer-Policy", config.ReferrerPolicy) } // Permissions Policy (formerly Feature-Policy) c.Header("Permissions-Policy", "geolocation=(), microphone=(), camera=()") // Cache control for API responses c.Header("Cache-Control", "no-store, no-cache, must-revalidate, proxy-revalidate") c.Header("Pragma", "no-cache") c.Header("Expires", "0") c.Next() } } // SecureHeaders is a convenience function that applies default security headers func SecureHeaders() gin.HandlerFunc { return SecurityHeaders(DefaultSecurityConfig()) }