From aace6002ee371f208e5abd9fab53ce39dd154bd9 Mon Sep 17 00:00:00 2001 From: silverwind Date: Wed, 3 Apr 2024 01:17:38 +0200 Subject: [PATCH] Move `cors.X_FRAME_OPTIONS` to `security.X_FRAME_OPTIONS` and add `false` option --- custom/conf/app.example.ini | 6 +++--- docs/content/administration/config-cheat-sheet.en-us.md | 2 +- docs/content/administration/config-cheat-sheet.zh-cn.md | 2 +- modules/setting/cors.go | 2 -- modules/setting/security.go | 2 ++ routers/common/errpage.go | 5 ++++- services/context/api.go | 5 ++++- services/context/context.go | 5 ++++- 8 files changed, 19 insertions(+), 10 deletions(-) diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini index 1584b10301..e4c0a9f28f 100644 --- a/custom/conf/app.example.ini +++ b/custom/conf/app.example.ini @@ -503,6 +503,9 @@ INTERNAL_TOKEN = ;; stemming from cached/logged plain-text API tokens. ;; In future releases, this will become the default behavior ;DISABLE_QUERY_AUTH_TOKEN = false +;; +;; The value of the X-FRAME-OPTIONS header for HTML and API requests. Set to 'false' to remove the header. +;X_FRAME_OPTIONS = SAMEORIGIN ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -1187,9 +1190,6 @@ LEVEL = Info ;; ;; headers to permit ;HEADERS = Content-Type,User-Agent -;; -;; set X-FRAME-OPTIONS header -;X_FRAME_OPTIONS = SAMEORIGIN ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/docs/content/administration/config-cheat-sheet.en-us.md b/docs/content/administration/config-cheat-sheet.en-us.md index f2209d269a..43ef54ec23 100644 --- a/docs/content/administration/config-cheat-sheet.en-us.md +++ b/docs/content/administration/config-cheat-sheet.en-us.md @@ -202,7 +202,6 @@ The following configuration set `Content-Type: application/vnd.android.package-a - `MAX_AGE`: **10m**: max time to cache response - `ALLOW_CREDENTIALS`: **false**: allow request with credentials - `HEADERS`: **Content-Type,User-Agent**: additional headers that are permitted in requests -- `X_FRAME_OPTIONS`: **SAMEORIGIN**: Set the `X-Frame-Options` header value. ## UI (`ui`) @@ -584,6 +583,7 @@ And the following unique queues: - `PASSWORD_CHECK_PWN`: **false**: Check [HaveIBeenPwned](https://haveibeenpwned.com/Passwords) to see if a password has been exposed. - `SUCCESSFUL_TOKENS_CACHE_SIZE`: **20**: Cache successful token hashes. API tokens are stored in the DB as pbkdf2 hashes however, this means that there is a potentially significant hashing load when there are multiple API operations. This cache will store the successfully hashed tokens in a LRU cache as a balance between performance and security. - `DISABLE_QUERY_AUTH_TOKEN`: **false**: Reject API tokens sent in URL query string (Accept Header-based API tokens only). This setting will default to `true` in Gitea 1.23 and be deprecated in Gitea 1.24. +- `X_FRAME_OPTIONS`: **SAMEORIGIN**: The value of the X-FRAME-OPTIONS header for HTML and API requests. Set to 'false' to remove the header. ## Camo (`camo`) diff --git a/docs/content/administration/config-cheat-sheet.zh-cn.md b/docs/content/administration/config-cheat-sheet.zh-cn.md index 41c8844ae5..e929e5b022 100644 --- a/docs/content/administration/config-cheat-sheet.zh-cn.md +++ b/docs/content/administration/config-cheat-sheet.zh-cn.md @@ -200,7 +200,6 @@ menu: - `MAX_AGE`: **10m**: 缓存响应的最大时间 - `ALLOW_CREDENTIALS`: **false**: 允许带有凭据的请求 - `HEADERS`: **Content-Type,User-Agent**: 允许请求携带的头部 -- `X_FRAME_OPTIONS`: **SAMEORIGIN**: 详见 `X-Frame-Options`HTTP头部. ## 界面 (`ui`) @@ -552,6 +551,7 @@ Gitea 创建以下非唯一队列: - off - 不检查密码复杂性 - `PASSWORD_CHECK_PWN`: **false**:检查密码是否在 [HaveIBeenPwned](https://haveibeenpwned.com/Passwords) 中曝光。 - `SUCCESSFUL_TOKENS_CACHE_SIZE`: **20**:缓存成功的令牌哈希。API 令牌在数据库中存储为 pbkdf2 哈希,但这意味着在存在多个 API 操作时可能会有显着的哈希负载。此缓存将在 LRU 缓存中存储成功的哈希令牌,以在性能和安全性之间保持平衡。 +- `X_FRAME_OPTIONS`: **SAMEORIGIN**: HTML 和 API 请求的 X-FRAME-OPTIONS 标头的值。 设置为“false”以删除标头。 ## Camo (`camo`) diff --git a/modules/setting/cors.go b/modules/setting/cors.go index 63daaad60b..15d534da79 100644 --- a/modules/setting/cors.go +++ b/modules/setting/cors.go @@ -17,13 +17,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", } func loadCorsFrom(rootCfg ConfigProvider) { diff --git a/modules/setting/security.go b/modules/setting/security.go index 3d7b1f9ce7..62395f2275 100644 --- a/modules/setting/security.go +++ b/modules/setting/security.go @@ -37,6 +37,7 @@ var ( DisableQueryAuthToken bool CSRFCookieName = "_csrf" CSRFCookieHTTPOnly = true + XFrameOptions string ) // loadSecret load the secret from ini by uriKey or verbatimKey, only one of them could be set @@ -139,6 +140,7 @@ func loadSecurityFrom(rootCfg ConfigProvider) { CSRFCookieHTTPOnly = sec.Key("CSRF_COOKIE_HTTP_ONLY").MustBool(true) PasswordCheckPwn = sec.Key("PASSWORD_CHECK_PWN").MustBool(false) SuccessfulTokensCacheSize = sec.Key("SUCCESSFUL_TOKENS_CACHE_SIZE").MustInt(20) + XFrameOptions = sec.Key("X_FRAME_OPTIONS").MustString("SAMEORIGIN") InternalToken = loadSecret(sec, "INTERNAL_TOKEN_URI", "INTERNAL_TOKEN") if InstallLock && InternalToken == "" { diff --git a/routers/common/errpage.go b/routers/common/errpage.go index 402ca44c12..7caf6e926e 100644 --- a/routers/common/errpage.go +++ b/routers/common/errpage.go @@ -34,7 +34,10 @@ func RenderPanicErrorPage(w http.ResponseWriter, req *http.Request, err any) { routing.UpdatePanicError(req.Context(), err) httpcache.SetCacheControlInHeader(w.Header(), 0, "no-transform") - w.Header().Set(`X-Frame-Options`, setting.CORSConfig.XFrameOptions) + + if setting.XFrameOptions != "false" { + w.Header().Set(`X-Frame-Options`, setting.XFrameOptions) + } tmplCtx := context.TemplateContext{} tmplCtx["Locale"] = middleware.Locale(w, req) diff --git a/services/context/api.go b/services/context/api.go index b18a206b5e..326667e58e 100644 --- a/services/context/api.go +++ b/services/context/api.go @@ -235,7 +235,10 @@ func APIContexter() func(http.Handler) http.Handler { } httpcache.SetCacheControlInHeader(ctx.Resp.Header(), 0, "no-transform") - ctx.Resp.Header().Set(`X-Frame-Options`, setting.CORSConfig.XFrameOptions) + + if setting.XFrameOptions != "false" { + ctx.Resp.Header().Set(`X-Frame-Options`, setting.XFrameOptions) + } next.ServeHTTP(ctx.Resp, ctx.Req) }) diff --git a/services/context/context.go b/services/context/context.go index 4b318f7e33..4a2e8eb268 100644 --- a/services/context/context.go +++ b/services/context/context.go @@ -190,7 +190,10 @@ func Contexter() func(next http.Handler) http.Handler { } httpcache.SetCacheControlInHeader(ctx.Resp.Header(), 0, "no-transform") - ctx.Resp.Header().Set(`X-Frame-Options`, setting.CORSConfig.XFrameOptions) + + if setting.XFrameOptions != "false" { + ctx.Resp.Header().Set(`X-Frame-Options`, setting.XFrameOptions) + } ctx.Data["SystemConfig"] = setting.Config() ctx.Data["CsrfToken"] = ctx.Csrf.GetToken()