[SEC-2191] Add security headers with sensible default values. (#21656)

* Add security headers with sensible default values.

* Add test to check that default security headers are added to http responses

* Also test the static handler.
Этот коммит содержится в:
Ossi Väänänen
2023-01-18 14:04:48 +02:00
коммит произвёл GitHub
родитель 544304d1c6
Коммит 62428467dc
3 изменённых файлов: 48 добавлений и 0 удалений

Просмотреть файл

@@ -235,6 +235,11 @@ func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Strict-Transport-Security", fmt.Sprintf("max-age=%d", *c.App.Config().ServiceSettings.TLSStrictTransportMaxAge))
}
// Hardcoded sensible default values for these security headers. Feel free to override in proxy or ingress
w.Header().Set("Permissions-Policy", "")
w.Header().Set("X-Content-Type-Options", "nosniff")
w.Header().Set("Referrer-Policy", "no-referrer")
cloudCSP := ""
if c.App.Channels().License().IsCloud() || *c.App.Config().ServiceSettings.SelfHostedPurchase {
cloudCSP = " js.stripe.com/v3"

Просмотреть файл

@@ -59,6 +59,44 @@ func TestHandlerServeHTTPErrors(t *testing.T) {
}
}
func handlerForServeDefaultSecurityHeaders(c *Context, w http.ResponseWriter, r *http.Request) {
}
func TestHandlerServeDefaultSecurityHeaders(t *testing.T) {
th := SetupWithStoreMock(t)
defer th.TearDown()
web := New(th.Server)
handler := web.NewHandler(handlerForServeDefaultSecurityHeaders)
paths := []string{
"/api/v4/test", // API
"/static/manifest.json", // this should always exist. Static files have their own handler
// Note that the plugin handler isn't tested, also plugins may support arbitrary functionality
}
for _, path := range paths {
request := httptest.NewRequest("GET", path, nil)
response := httptest.NewRecorder()
handler.ServeHTTP(response, request)
// header.Get returns a "" also if the header doesn't exist so we check that there is at least
// one Permissions-Policy header and their value is "". We check with .Values() as it canonicalizes
// the key.
permissionsPolicyHeader := response.Header().Get("Permissions-Policy")
permissionsPolicyHeaderValues := response.Header().Values("Permissions-Policy")
contentTypeOptionsHeader := response.Header().Get("X-Content-Type-Options")
referrerPolicyHeader := response.Header().Get("Referrer-Policy")
assert.NotEqualf(t, 0, len(permissionsPolicyHeaderValues), "Permissions-Policy header doesn't exist")
assert.Equal(t, "", permissionsPolicyHeader, "Permissions-Policy is not empty")
assert.Equal(t, "nosniff", contentTypeOptionsHeader)
assert.Equal(t, "no-referrer", referrerPolicyHeader)
}
}
func handlerForHTTPSecureTransport(c *Context, w http.ResponseWriter, r *http.Request) {
}

Просмотреть файл

@@ -87,6 +87,11 @@ func staticFilesHandler(handler http.Handler) http.Handler {
w.Header().Set("Cache-Control", "max-age=31556926, public")
}
// Hardcoded sensible default values for these security headers. Feel free to override in proxy or ingress
w.Header().Set("Permissions-Policy", "")
w.Header().Set("X-Content-Type-Options", "nosniff")
w.Header().Set("Referrer-Policy", "no-referrer")
if strings.HasSuffix(r.URL.Path, "/") {
http.NotFound(w, r)
return