Security Headers
It’s important to use security headers to protect your web application from common security vulnerabilities. This example shows you how to add security headers to your Gin application and also how to avoid Host Header Injection related attacks (SSRF, Open Redirection).
package main
import ( "net/http"
"github.com/gin-gonic/gin")
func main() { r := gin.Default()
expectedHost := "localhost:8080"
// Setup Security Headers r.Use(func(c *gin.Context) { if c.Request.Host != expectedHost { c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "Invalid host header"}) return } c.Header("X-Frame-Options", "DENY") c.Header("Content-Security-Policy", "default-src 'self'; connect-src *; font-src *; script-src-elem * 'unsafe-inline'; img-src * data:; style-src * 'unsafe-inline';") c.Header("X-XSS-Protection", "1; mode=block") c.Header("Strict-Transport-Security", "max-age=31536000; includeSubDomains; preload") c.Header("Referrer-Policy", "strict-origin") c.Header("X-Content-Type-Options", "nosniff") c.Header("Permissions-Policy", "geolocation=(),midi=(),sync-xhr=(),microphone=(),camera=(),magnetometer=(),gyroscope=(),fullscreen=(self),payment=()") c.Next() })
r.GET("/ping", func(c *gin.Context) { c.JSON(200, gin.H{ "message": "pong", }) })
r.Run() // listen and serve on 0.0.0.0:8080}
You can test it via curl
:
// Check Headers
curl localhost:8080/ping -I
HTTP/1.1 404 Not FoundContent-Security-Policy: default-src 'self'; connect-src *; font-src *; script-src-elem * 'unsafe-inline'; img-src * data:; style-src * 'unsafe-inline';Content-Type: text/plainPermissions-Policy: geolocation=(),midi=(),sync-xhr=(),microphone=(),camera=(),magnetometer=(),gyroscope=(),fullscreen=(self),payment=()Referrer-Policy: strict-originStrict-Transport-Security: max-age=31536000; includeSubDomains; preloadX-Content-Type-Options: nosniffX-Frame-Options: DENYX-Xss-Protection: 1; mode=blockDate: Sat, 30 Mar 2024 08:20:44 GMTContent-Length: 18
// Check Host Header Injection
curl localhost:8080/ping -I -H "Host:neti.ee"
HTTP/1.1 400 Bad RequestContent-Type: application/json; charset=utf-8Date: Sat, 30 Mar 2024 08:21:09 GMTContent-Length: 31