0
0
mirror of https://github.com/go-gitea/gitea.git synced 2026-02-23 21:33:19 +01:00

Move X_FRAME_OPTIONS setting from cors to security section (#30256)

## Summary

- Move `cors.X_FRAME_OPTIONS` to `security.X_FRAME_OPTIONS` (old
location still works with a deprecation warning)
- Support `"unset"` as a special value to remove the `X-Frame-Options`
header entirely
- Remove `X-Frame-Options` header from API responses (only set for
web/HTML responses)

## Migration

If you had customized `cors.X_FRAME_OPTIONS`, move it to the
`[security]` section. The old location is deprecated and will be removed
in a future release.

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
silverwind 2026-02-22 21:26:46 +01:00 committed by GitHub
parent fed2d81e88
commit 5f8e19fcef
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 27 additions and 13 deletions

View File

@ -521,6 +521,9 @@ INTERNAL_TOKEN =
;; Set the two-factor auth behavior.
;; Set to "enforced", to force users to enroll into Two-Factor Authentication, users without 2FA have no access to repositories via API or web.
;TWO_FACTOR_AUTH =
;;
;; The value of the X-Frame-Options HTTP header for HTML responses. Use "unset" to remove the header.
;X_FRAME_OPTIONS = SAMEORIGIN
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -1290,9 +1293,6 @@ LEVEL = Info
;;
;; headers to permit
;HEADERS = Content-Type,User-Agent
;;
;; set X-FRAME-OPTIONS header
;X_FRAME_OPTIONS = SAMEORIGIN
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -15,13 +15,11 @@ var CORSConfig = struct {
MaxAge time.Duration
AllowCredentials bool
Headers []string
XFrameOptions string
}{
AllowDomain: []string{"*"},
Methods: []string{"GET", "HEAD", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"},
Headers: []string{"Content-Type", "User-Agent"},
MaxAge: 10 * time.Minute,
XFrameOptions: "SAMEORIGIN",
AllowDomain: []string{"*"},
Methods: []string{"GET", "HEAD", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"},
Headers: []string{"Content-Type", "User-Agent"},
MaxAge: 10 * time.Minute,
}
func loadCorsFrom(rootCfg ConfigProvider) {

View File

@ -14,6 +14,12 @@ import (
)
// Security settings
var Security = struct {
// TODO: move more settings to this struct in future
XFrameOptions string
}{
XFrameOptions: "SAMEORIGIN",
}
var (
InstallLock bool
@ -140,6 +146,13 @@ func loadSecurityFrom(rootCfg ConfigProvider) {
PasswordCheckPwn = sec.Key("PASSWORD_CHECK_PWN").MustBool(false)
SuccessfulTokensCacheSize = sec.Key("SUCCESSFUL_TOKENS_CACHE_SIZE").MustInt(20)
deprecatedSetting(rootCfg, "cors", "X_FRAME_OPTIONS", "security", "X_FRAME_OPTIONS", "v1.26.0")
if sec.HasKey("X_FRAME_OPTIONS") {
Security.XFrameOptions = sec.Key("X_FRAME_OPTIONS").MustString(Security.XFrameOptions)
} else {
Security.XFrameOptions = rootCfg.Section("cors").Key("X_FRAME_OPTIONS").MustString(Security.XFrameOptions)
}
twoFactorAuth := sec.Key("TWO_FACTOR_AUTH").String()
switch twoFactorAuth {
case "":

View File

@ -32,7 +32,9 @@ func renderServerErrorPage(w http.ResponseWriter, req *http.Request, respCode in
}
httpcache.SetCacheControlInHeader(w.Header(), &httpcache.CacheControlOptions{NoTransform: true})
w.Header().Set(`X-Frame-Options`, setting.CORSConfig.XFrameOptions)
if setting.Security.XFrameOptions != "unset" {
w.Header().Set(`X-Frame-Options`, setting.Security.XFrameOptions)
}
tmplCtx := context.NewTemplateContext(req.Context(), req)
tmplCtx["Locale"] = middleware.Locale(w, req)

View File

@ -235,8 +235,6 @@ func APIContexter() func(http.Handler) http.Handler {
}
httpcache.SetCacheControlInHeader(ctx.Resp.Header(), &httpcache.CacheControlOptions{NoTransform: true})
ctx.Resp.Header().Set(`X-Frame-Options`, setting.CORSConfig.XFrameOptions)
next.ServeHTTP(ctx.Resp, ctx.Req)
})
}

View File

@ -196,7 +196,10 @@ func Contexter() func(next http.Handler) http.Handler {
}
httpcache.SetCacheControlInHeader(ctx.Resp.Header(), &httpcache.CacheControlOptions{NoTransform: true})
ctx.Resp.Header().Set(`X-Frame-Options`, setting.CORSConfig.XFrameOptions)
if setting.Security.XFrameOptions != "unset" {
ctx.Resp.Header().Set(`X-Frame-Options`, setting.Security.XFrameOptions)
}
ctx.Data["SystemConfig"] = setting.Config()