File tree 4 files changed +47
-3
lines changed
4 files changed +47
-3
lines changed Original file line number Diff line number Diff line change @@ -101,7 +101,6 @@ func New(options *Options) *API {
101
101
Message : "Route not found." ,
102
102
})
103
103
})
104
-
105
104
r .Use (
106
105
// Specific routes can specify smaller limits.
107
106
httpmw .RateLimitPerMinute (options .APIRateLimit ),
@@ -112,6 +111,9 @@ func New(options *Options) *API {
112
111
Message : "👋" ,
113
112
})
114
113
})
114
+ // All CSP errors will be logged
115
+ r .Post ("/csp/reports" , api .logReportCSPViolations )
116
+
115
117
r .Route ("/buildinfo" , func (r chi.Router ) {
116
118
r .Get ("/" , func (rw http.ResponseWriter , r * http.Request ) {
117
119
httpapi .Write (rw , http .StatusOK , codersdk.BuildInfoResponse {
Original file line number Diff line number Diff line change @@ -119,6 +119,7 @@ func TestAuthorizeAllEndpoints(t *testing.T) {
119
119
"POST:/api/v2/users/login" : {NoAuthorize : true },
120
120
"POST:/api/v2/users/logout" : {NoAuthorize : true },
121
121
"GET:/api/v2/users/authmethods" : {NoAuthorize : true },
122
+ "POST:/api/v2/csp/reports" : {NoAuthorize : true },
122
123
123
124
// Has it's own auth
124
125
"GET:/api/v2/users/oauth2/github/callback" : {NoAuthorize : true },
Original file line number Diff line number Diff line change
1
+ package coderd
2
+
3
+ import (
4
+ "encoding/json"
5
+ "net/http"
6
+
7
+ "github.com/coder/coder/coderd/httpapi"
8
+
9
+ "cdr.dev/slog"
10
+ )
11
+
12
+ type cspViolation struct {
13
+ Report map [string ]interface {} `json:"csp-report"`
14
+ }
15
+
16
+ // logReportCSPViolations will log all reported csp violations.
17
+ func (api * API ) logReportCSPViolations (rw http.ResponseWriter , r * http.Request ) {
18
+ ctx := r .Context ()
19
+ var v cspViolation
20
+
21
+ dec := json .NewDecoder (r .Body )
22
+ err := dec .Decode (& v )
23
+ if err != nil {
24
+ api .Logger .Warn (ctx , "csp violation" , slog .Error (err ))
25
+ httpapi .Write (rw , http .StatusBadRequest , httpapi.Response {
26
+ Message : "failed to read body" ,
27
+ })
28
+ return
29
+ }
30
+
31
+ fields := make ([]slog.Field , 0 , len (v .Report ))
32
+ for k , v := range v .Report {
33
+ fields = append (fields , slog .F (k , v ))
34
+ }
35
+ api .Logger .Warn (ctx , "csp violation" , fields ... )
36
+
37
+ httpapi .Write (rw , http .StatusOK , "ok" )
38
+ }
Original file line number Diff line number Diff line change @@ -261,11 +261,14 @@ func secureHeaders(next http.Handler) http.Handler {
261
261
CSPDirectiveManifestSrc : {"'self' blob:" },
262
262
CSPDirectiveFrameSrc : {"'self'" },
263
263
// data: for loading base64 encoded icons for generic applications.
264
- CSPDirectiveImgSrc : {"'self' https://cdn.coder.com data:" },
264
+ // https: allows loading images from external sources. This is not ideal
265
+ // but is required for the templates page that renders readmes.
266
+ // We should find a better solution in the future.
267
+ CSPDirectiveImgSrc : {"'self' https: https://cdn.coder.com data:" },
265
268
CSPDirectiveFormAction : {"'self'" },
266
269
CSPDirectiveMediaSrc : {"'self'" },
267
270
// Report all violations back to the server to log
268
- CSPDirectiveReportURI : {"/api/private /csp/reports" },
271
+ CSPDirectiveReportURI : {"/api/v2 /csp/reports" },
269
272
CSPFrameAncestors : {"'none'" },
270
273
271
274
// Only scripts can manipulate the dom. This prevents someone from
You can’t perform that action at this time.
0 commit comments