This commit is contained in:
delete 2026-06-10 20:51:17 +03:00
commit b15b95781c
108 changed files with 14802 additions and 0 deletions

80
internal/http/security.go Normal file
View file

@ -0,0 +1,80 @@
package httpserver
import (
"net/http"
"strings"
"update_server/internal/config"
)
const contentSecurityPolicy = "default-src 'self'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'; img-src 'self' data:; object-src 'none'; script-src 'self'; style-src 'self'"
func securityHeaders(cfg config.Config) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
headers := w.Header()
headers.Set("Content-Security-Policy", contentSecurityPolicy)
headers.Set("Cross-Origin-Opener-Policy", "same-origin")
headers.Set("Cross-Origin-Resource-Policy", "same-origin")
headers.Set("Permissions-Policy", "camera=(), geolocation=(), microphone=()")
headers.Set("Referrer-Policy", "no-referrer")
headers.Set("X-Content-Type-Options", "nosniff")
headers.Set("X-Frame-Options", "DENY")
if cfg.SecureCookies {
headers.Set("Strict-Transport-Security", "max-age=31536000")
}
next.ServeHTTP(w, r)
})
}
}
func adminResponseHeaders(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
applyNoStoreHeaders(w)
addVaryHeader(w, "Cookie")
w.Header().Set("X-Robots-Tag", "noindex, nofollow")
next.ServeHTTP(w, r)
})
}
func apiResponseHeaders(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("X-Robots-Tag", "noindex, nofollow")
next.ServeHTTP(w, r)
})
}
func protectedAPIResponseHeaders(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
applyNoStoreHeaders(w)
addVaryHeader(w, "Authorization")
w.Header().Set("X-Robots-Tag", "noindex, nofollow")
next.ServeHTTP(w, r)
})
}
func applyNoStoreHeaders(w http.ResponseWriter) {
w.Header().Set("Cache-Control", "no-store, private, max-age=0")
w.Header().Set("Pragma", "no-cache")
w.Header().Set("Expires", "0")
}
func addVaryHeader(w http.ResponseWriter, value string) {
value = strings.TrimSpace(value)
if value == "" {
return
}
current := w.Header().Values("Vary")
for _, entry := range current {
for _, existing := range strings.Split(entry, ",") {
if strings.EqualFold(strings.TrimSpace(existing), value) {
return
}
}
}
w.Header().Add("Vary", value)
}