feat(security): set X-Content-Type-Options: nosniff by default (#37354)

Fixes #37316.

---------

Signed-off-by: SAY-5 <SAY-5@users.noreply.github.com>
Co-authored-by: SAY-5 <SAY-5@users.noreply.github.com>
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: Claude (Opus 4.7) <noreply@anthropic.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
Sai Asish Y
2026-04-24 04:21:34 -07:00
committed by GitHub
parent 1483291a87
commit 6826321570
7 changed files with 45 additions and 26 deletions
+16
View File
@@ -28,6 +28,7 @@ func ProtocolMiddlewares() (handlers []any) {
// the order is important
handlers = append(handlers, ChiRoutePathHandler()) // make sure chi has correct paths
handlers = append(handlers, RequestContextHandler()) // prepare the context and panic recovery
handlers = append(handlers, SecurityHeadersHandler())
if setting.ReverseProxyLimit > 0 && len(setting.ReverseProxyTrustedProxies) > 0 {
handlers = append(handlers, ForwardedHeadersHandler(setting.ReverseProxyLimit, setting.ReverseProxyTrustedProxies))
@@ -48,6 +49,21 @@ func ProtocolMiddlewares() (handlers []any) {
return handlers
}
// SecurityHeadersHandler sets headers globally for every response that leaves Gitea.
func SecurityHeadersHandler() func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
if setting.Security.XContentTypeOptions != "unset" {
resp.Header().Set("X-Content-Type-Options", setting.Security.XContentTypeOptions)
}
if setting.Security.XFrameOptions != "unset" {
resp.Header().Set("X-Frame-Options", setting.Security.XFrameOptions)
}
next.ServeHTTP(resp, req)
})
}
}
func RequestContextHandler() func(h http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(respOrig http.ResponseWriter, req *http.Request) {