fix(coderd): omit frame-ancestors CSP for embed routes (#24529)

This commit is contained in:
Jakub Domeracki
2026-04-20 15:38:52 +02:00
committed by GitHub
parent 410f9a5e19
commit 411ed21059
3 changed files with 38 additions and 7 deletions
+10 -1
View File
@@ -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
+20 -2
View File
@@ -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) {