package middleware import ( "net/http" "strings" "github.com/gin-gonic/gin" ) // OriginProtection blocks browser-driven cross-site requests to localhost. // Same-origin UI requests continue to work; CLI clients without Origin/Referer remain allowed. func OriginProtection() gin.HandlerFunc { return func(c *gin.Context) { if isSafeMethod(c.Request.Method) { c.Next() return } if secFetchSite := strings.TrimSpace(c.GetHeader("Sec-Fetch-Site")); secFetchSite == "cross-site" { c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"error": "cross-site requests are not allowed"}) return } if origin := strings.TrimSpace(c.GetHeader("Origin")); origin != "" && !isLoopbackOrigin(origin) { c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"error": "origin must be localhost"}) return } if referer := strings.TrimSpace(c.GetHeader("Referer")); referer != "" && !isLoopbackOrigin(referer) { c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"error": "referer must be localhost"}) return } c.Next() } } func isSafeMethod(method string) bool { switch method { case http.MethodGet, http.MethodHead, http.MethodOptions: return true default: return false } }