mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
fix(coderd): omit frame-ancestors CSP for embed routes (#24529)
This commit is contained in:
+10
-1
@@ -145,8 +145,17 @@ func CSPHeaders(telemetry bool, proxyHosts func() []*proxyhealth.ProxyHost, stat
|
||||
// Default to 'self' to prevent clickjacking unless
|
||||
// explicitly overridden via staticAdditions (e.g. for
|
||||
// embeddable routes).
|
||||
if _, ok := cspSrcs[CSPFrameAncestors]; !ok {
|
||||
//
|
||||
// An explicit empty value means "omit frame-ancestors
|
||||
// entirely", which is needed for embed routes where
|
||||
// non-network-scheme parents (e.g. vscode-webview://)
|
||||
// must be able to frame the page. The CSP wildcard '*'
|
||||
// only matches network schemes (http, https, ws, wss)
|
||||
// so it cannot cover custom schemes.
|
||||
if vals, ok := cspSrcs[CSPFrameAncestors]; !ok {
|
||||
cspSrcs[CSPFrameAncestors] = []string{"'self'"}
|
||||
} else if len(vals) == 0 {
|
||||
delete(cspSrcs, CSPFrameAncestors)
|
||||
}
|
||||
|
||||
var csp strings.Builder
|
||||
|
||||
@@ -40,15 +40,33 @@ func TestCSPFrameAncestors(t *testing.T) {
|
||||
httpmw.CSPHeaders(false, func() []*proxyhealth.ProxyHost {
|
||||
return nil
|
||||
}, map[httpmw.CSPFetchDirective][]string{
|
||||
httpmw.CSPFrameAncestors: {"*"},
|
||||
httpmw.CSPFrameAncestors: {"https://example.com"},
|
||||
})(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
})).ServeHTTP(rw, r)
|
||||
|
||||
csp := rw.Header().Get("Content-Security-Policy")
|
||||
require.Contains(t, csp, "frame-ancestors *")
|
||||
require.Contains(t, csp, "frame-ancestors https://example.com")
|
||||
require.NotContains(t, csp, "frame-ancestors 'self'")
|
||||
})
|
||||
|
||||
t.Run("OmitWhenEmpty", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
r := httptest.NewRequest(http.MethodGet, "/", nil)
|
||||
rw := httptest.NewRecorder()
|
||||
|
||||
httpmw.CSPHeaders(false, func() []*proxyhealth.ProxyHost {
|
||||
return nil
|
||||
}, map[httpmw.CSPFetchDirective][]string{
|
||||
httpmw.CSPFrameAncestors: {},
|
||||
})(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
})).ServeHTTP(rw, r)
|
||||
|
||||
csp := rw.Header().Get("Content-Security-Policy")
|
||||
require.NotContains(t, csp, "frame-ancestors")
|
||||
})
|
||||
}
|
||||
|
||||
func TestCSP(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user