From f41f00fec20db26690a1edc2dbda753e6bd65ff5 Mon Sep 17 00:00:00 2001 From: Nicola Murino Date: Mon, 7 Apr 2025 18:48:48 +0200 Subject: [PATCH] httpd: allow to configure referrer policy header Signed-off-by: Nicola Murino --- internal/config/config.go | 6 ++++++ internal/config/config_test.go | 4 ++++ internal/httpd/httpd.go | 6 ++++-- internal/httpd/internal_test.go | 2 ++ internal/httpd/server.go | 1 + sftpgo.json | 1 + 6 files changed, 18 insertions(+), 2 deletions(-) diff --git a/internal/config/config.go b/internal/config/config.go index 34feb21b..f3a3237c 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -1586,6 +1586,12 @@ func getHTTPDSecurityConfFromEnv(idx int) (httpd.SecurityConf, bool) { //nolint: isSet = true } + referredPolicy, ok := os.LookupEnv(fmt.Sprintf("SFTPGO_HTTPD__BINDINGS__%v__SECURITY__REFERRER_POLICY", idx)) + if ok { + result.ReferrerPolicy = referredPolicy + isSet = true + } + cacheControl, ok := os.LookupEnv(fmt.Sprintf("SFTPGO_HTTPD__BINDINGS__%v__SECURITY__CACHE_CONTROL", idx)) if ok { result.CacheControl = cacheControl diff --git a/internal/config/config_test.go b/internal/config/config_test.go index a3cefa9e..f908953d 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -1234,6 +1234,7 @@ func TestHTTPDBindingsFromEnv(t *testing.T) { os.Setenv("SFTPGO_HTTPD__BINDINGS__2__SECURITY__CROSS_ORIGIN_RESOURCE_POLICY", "same-site") os.Setenv("SFTPGO_HTTPD__BINDINGS__2__SECURITY__CROSS_ORIGIN_EMBEDDER_POLICY", "require-corp") os.Setenv("SFTPGO_HTTPD__BINDINGS__2__SECURITY__CACHE_CONTROL", "private") + os.Setenv("SFTPGO_HTTPD__BINDINGS__2__SECURITY__REFERRER_POLICY", "no-referrer") os.Setenv("SFTPGO_HTTPD__BINDINGS__2__EXTRA_CSS__0__PATH", "path1") os.Setenv("SFTPGO_HTTPD__BINDINGS__2__EXTRA_CSS__1__PATH", "path2") os.Setenv("SFTPGO_HTTPD__BINDINGS__2__BRANDING__WEB_ADMIN__FAVICON_PATH", "favicon.ico") @@ -1304,6 +1305,7 @@ func TestHTTPDBindingsFromEnv(t *testing.T) { os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__SECURITY__CROSS_ORIGIN_RESOURCE_POLICY") os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__SECURITY__CROSS_ORIGIN_EMBEDDER_POLICY") os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__SECURITY__CACHE_CONTROL") + os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__SECURITY__REFERRER_POLICY") os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__EXTRA_CSS__0__PATH") os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__EXTRA_CSS__1__PATH") os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__BRANDING__WEB_ADMIN__FAVICON_PATH") @@ -1343,6 +1345,7 @@ func TestHTTPDBindingsFromEnv(t *testing.T) { require.Len(t, bindings[0].OIDC.Scopes, 3) require.False(t, bindings[0].OIDC.InsecureSkipSignatureCheck) require.False(t, bindings[0].OIDC.Debug) + require.Empty(t, bindings[0].Security.ReferrerPolicy) require.Equal(t, 8000, bindings[1].Port) require.Equal(t, "127.0.0.1", bindings[1].Address) require.False(t, bindings[1].EnableHTTPS) @@ -1429,6 +1432,7 @@ func TestHTTPDBindingsFromEnv(t *testing.T) { require.Equal(t, "same-site", bindings[2].Security.CrossOriginResourcePolicy) require.Equal(t, "require-corp", bindings[2].Security.CrossOriginEmbedderPolicy) require.Equal(t, "private", bindings[2].Security.CacheControl) + require.Equal(t, "no-referrer", bindings[2].Security.ReferrerPolicy) require.Equal(t, "favicon.ico", bindings[2].Branding.WebAdmin.FaviconPath) require.Equal(t, "logo.png", bindings[2].Branding.WebClient.LogoPath) require.Equal(t, "disclaimer", bindings[2].Branding.WebClient.DisclaimerName) diff --git a/internal/httpd/httpd.go b/internal/httpd/httpd.go index deba2e38..203536c0 100644 --- a/internal/httpd/httpd.go +++ b/internal/httpd/httpd.go @@ -420,9 +420,11 @@ type SecurityConf struct { CrossOriginResourcePolicy string `json:"cross_origin_resource_policy" mapstructure:"cross_origin_resource_policy"` // CrossOriginEmbedderPolicy allows to set the Cross-Origin-Embedder-Policy header value. Default is "". CrossOriginEmbedderPolicy string `json:"cross_origin_embedder_policy" mapstructure:"cross_origin_embedder_policy"` - // CacheControl allow to set the Cache-Control header value. + // CacheControl allows to set the Cache-Control header value. CacheControl string `json:"cache_control" mapstructure:"cache_control"` - proxyHeaders []string + // ReferrerPolicy allows to set the Referrer-Policy header values. + ReferrerPolicy string `json:"referrer_policy" mapstructure:"referrer_policy"` + proxyHeaders []string } func (s *SecurityConf) updateProxyHeaders() { diff --git a/internal/httpd/internal_test.go b/internal/httpd/internal_test.go index 278c78b3..551dbdd7 100644 --- a/internal/httpd/internal_test.go +++ b/internal/httpd/internal_test.go @@ -3446,6 +3446,7 @@ func TestSecureMiddlewareIntegration(t *testing.T) { CrossOriginOpenerPolicy: "same-origin", CrossOriginResourcePolicy: "same-site", CrossOriginEmbedderPolicy: "require-corp", + ReferrerPolicy: "no-referrer", }, }, enableWebAdmin: true, @@ -3503,6 +3504,7 @@ func TestSecureMiddlewareIntegration(t *testing.T) { assert.Equal(t, "require-corp", rr.Header().Get("Cross-Origin-Embedder-Policy")) assert.Equal(t, "same-origin", rr.Header().Get("Cross-Origin-Opener-Policy")) assert.Equal(t, "same-site", rr.Header().Get("Cross-Origin-Resource-Policy")) + assert.Equal(t, "no-referrer", rr.Header().Get("Referrer-Policy")) server.binding.Security.Enabled = false server.binding.Security.updateProxyHeaders() diff --git a/internal/httpd/server.go b/internal/httpd/server.go index 217afb07..381adede 100644 --- a/internal/httpd/server.go +++ b/internal/httpd/server.go @@ -1257,6 +1257,7 @@ func (s *httpdServer) initializeRouter() { CrossOriginOpenerPolicy: s.binding.Security.CrossOriginOpenerPolicy, CrossOriginResourcePolicy: s.binding.Security.CrossOriginResourcePolicy, CrossOriginEmbedderPolicy: s.binding.Security.CrossOriginEmbedderPolicy, + ReferrerPolicy: s.binding.Security.ReferrerPolicy, }) secureMiddleware.SetBadHostHandler(http.HandlerFunc(s.badHostHandler)) if s.binding.Security.CacheControl == "private" { diff --git a/sftpgo.json b/sftpgo.json index 20361311..f77d1afb 100644 --- a/sftpgo.json +++ b/sftpgo.json @@ -324,6 +324,7 @@ "cross_origin_opener_policy": "", "cross_origin_resource_policy": "", "cross_origin_embedder_policy": "", + "referrer_policy": "", "cache_control": "" }, "branding": {