Skip to content

Commit e4648b6

Browse files
authored
feat: allow iframing urls on the same domain as the deployment (coder#18102)
Used for AI tasks. We should eventually add regions to this csp header.
1 parent 201b0b1 commit e4648b6

File tree

3 files changed

+28
-14
lines changed

3 files changed

+28
-14
lines changed

coderd/coderd.go

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1532,17 +1532,19 @@ func New(options *Options) *API {
15321532

15331533
// Add CSP headers to all static assets and pages. CSP headers only affect
15341534
// browsers, so these don't make sense on api routes.
1535-
cspMW := httpmw.CSPHeaders(options.Telemetry.Enabled(), func() []string {
1536-
if api.DeploymentValues.Dangerous.AllowAllCors {
1537-
// In this mode, allow all external requests
1538-
return []string{"*"}
1539-
}
1540-
if f := api.WorkspaceProxyHostsFn.Load(); f != nil {
1541-
return (*f)()
1542-
}
1543-
// By default we do not add extra websocket connections to the CSP
1544-
return []string{}
1545-
}, additionalCSPHeaders)
1535+
cspMW := httpmw.CSPHeaders(
1536+
api.Experiments,
1537+
options.Telemetry.Enabled(), func() []string {
1538+
if api.DeploymentValues.Dangerous.AllowAllCors {
1539+
// In this mode, allow all external requests
1540+
return []string{"*"}
1541+
}
1542+
if f := api.WorkspaceProxyHostsFn.Load(); f != nil {
1543+
return (*f)()
1544+
}
1545+
// By default we do not add extra websocket connections to the CSP
1546+
return []string{}
1547+
}, additionalCSPHeaders)
15461548

15471549
// Static file handler must be wrapped with HSTS handler if the
15481550
// StrictTransportSecurityAge is set. We only need to set this header on

coderd/httpmw/csp.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"fmt"
55
"net/http"
66
"strings"
7+
8+
"github.com/coder/coder/v2/codersdk"
79
)
810

911
// cspDirectives is a map of all csp fetch directives to their values.
@@ -37,6 +39,7 @@ const (
3739
CSPDirectiveFormAction CSPFetchDirective = "form-action"
3840
CSPDirectiveMediaSrc CSPFetchDirective = "media-src"
3941
CSPFrameAncestors CSPFetchDirective = "frame-ancestors"
42+
CSPFrameSource CSPFetchDirective = "frame-src"
4043
CSPDirectiveWorkerSrc CSPFetchDirective = "worker-src"
4144
)
4245

@@ -55,7 +58,7 @@ const (
5558
// Example: https://github.com/coder/coder/issues/15118
5659
//
5760
//nolint:revive
58-
func CSPHeaders(telemetry bool, websocketHosts func() []string, staticAdditions map[CSPFetchDirective][]string) func(next http.Handler) http.Handler {
61+
func CSPHeaders(experiments codersdk.Experiments, telemetry bool, websocketHosts func() []string, staticAdditions map[CSPFetchDirective][]string) func(next http.Handler) http.Handler {
5962
return func(next http.Handler) http.Handler {
6063
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
6164
// Content-Security-Policy disables loading certain content types and can prevent XSS injections.
@@ -88,13 +91,21 @@ func CSPHeaders(telemetry bool, websocketHosts func() []string, staticAdditions
8891
CSPDirectiveMediaSrc: {"'self'"},
8992
// Report all violations back to the server to log
9093
CSPDirectiveReportURI: {"/api/v2/csp/reports"},
91-
CSPFrameAncestors: {"'none'"},
9294

9395
// Only scripts can manipulate the dom. This prevents someone from
9496
// naming themselves something like '<svg onload="alert(/cross-site-scripting/)" />'.
9597
// "require-trusted-types-for" : []string{"'script'"},
9698
}
9799

100+
if experiments.Enabled(codersdk.ExperimentAITasks) {
101+
// AI tasks use iframe embeds of local apps.
102+
// TODO: Handle region domains too, not just path based apps
103+
cspSrcs.Append(CSPFrameAncestors, `'self'`)
104+
cspSrcs.Append(CSPFrameSource, `'self'`)
105+
} else {
106+
cspSrcs.Append(CSPFrameAncestors, `'none'`)
107+
}
108+
98109
if telemetry {
99110
// If telemetry is enabled, we report to coder.com.
100111
cspSrcs.Append(CSPDirectiveConnectSrc, "https://coder.com")

coderd/httpmw/csp_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"github.com/stretchr/testify/require"
1010

1111
"github.com/coder/coder/v2/coderd/httpmw"
12+
"github.com/coder/coder/v2/codersdk"
1213
)
1314

1415
func TestCSPConnect(t *testing.T) {
@@ -20,7 +21,7 @@ func TestCSPConnect(t *testing.T) {
2021
r := httptest.NewRequest(http.MethodGet, "/", nil)
2122
rw := httptest.NewRecorder()
2223

23-
httpmw.CSPHeaders(false, func() []string {
24+
httpmw.CSPHeaders(codersdk.Experiments{}, false, func() []string {
2425
return expected
2526
}, map[httpmw.CSPFetchDirective][]string{
2627
httpmw.CSPDirectiveMediaSrc: expectedMedia,

0 commit comments

Comments
 (0)