@@ -256,48 +256,70 @@ const (
256
256
CSPFrameAncestors = "frame-ancestors"
257
257
)
258
258
259
+ func cspHeaders (next http.Handler ) http.Handler {
260
+ return http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
261
+ // Content-Security-Policy disables loading certain content types and can prevent XSS injections.
262
+ // This site helps eval your policy for syntax and other common issues: https://csp-evaluator.withgoogle.com/
263
+ // If we ever want to render something like a PDF, we need to adjust "object-src"
264
+ //
265
+ // The list of CSP options: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/default-src
266
+ cspSrcs := CSPDirectives {
267
+ // All omitted fetch csp srcs default to this.
268
+ CSPDirectiveDefaultSrc : {"'self'" },
269
+ CSPDirectiveConnectSrc : {"'self'" },
270
+ CSPDirectiveChildSrc : {"'self'" },
271
+ CSPDirectiveScriptSrc : {"'self'" },
272
+ CSPDirectiveFontSrc : {"'self'" },
273
+ CSPDirectiveStyleSrc : {"'self' 'unsafe-inline'" },
274
+ // object-src is needed to support code-server
275
+ CSPDirectiveObjectSrc : {"'self'" },
276
+ // blob: for loading the pwa manifest for code-server
277
+ CSPDirectiveManifestSrc : {"'self' blob:" },
278
+ CSPDirectiveFrameSrc : {"'self'" },
279
+ // data: for loading base64 encoded icons for generic applications.
280
+ // https: allows loading images from external sources. This is not ideal
281
+ // but is required for the templates page that renders readmes.
282
+ // We should find a better solution in the future.
283
+ CSPDirectiveImgSrc : {"'self' data:" },
284
+ CSPDirectiveFormAction : {"'self'" },
285
+ CSPDirectiveMediaSrc : {"'self'" },
286
+ // Report all violations back to the server to log
287
+ CSPDirectiveReportURI : {"/api/v2/csp/reports" },
288
+ CSPFrameAncestors : {"'none'" },
289
+
290
+ // Only scripts can manipulate the dom. This prevents someone from
291
+ // naming themselves something like '<svg onload="alert(/cross-site-scripting/)" />'.
292
+ // "require-trusted-types-for" : []string{"'script'"},
293
+ }
294
+
295
+ // This extra connect-src addition is required to support old webkit
296
+ // based browsers (Safari).
297
+ // See issue: https://github.com/w3c/webappsec-csp/issues/7
298
+ // Once webkit browsers support 'self' on connect-src, we can remove this.
299
+ // When we remove this, the csp header can be static, as opposed to being
300
+ // dynamically generated for each request.
301
+ host := r .Host
302
+ // It is important r.Host is not an empty string.
303
+ if host != "" {
304
+ // We can add both ws:// and wss:// as browsers do not let https
305
+ // pages to connect to non-tls websocket connections. So this
306
+ // supports both http & https webpages.
307
+ cspSrcs .Append (CSPDirectiveConnectSrc , fmt .Sprintf ("wss://%[1]s ws://%[1]s" , host ))
308
+ }
309
+
310
+ var csp strings.Builder
311
+ for src , vals := range cspSrcs {
312
+ _ , _ = fmt .Fprintf (& csp , "%s %s; " , src , strings .Join (vals , " " ))
313
+ }
314
+
315
+ w .Header ().Set ("Content-Security-Policy" , csp .String ())
316
+ next .ServeHTTP (w , r )
317
+ })
318
+ }
319
+
259
320
// secureHeaders is only needed for statically served files. We do not need this for api endpoints.
260
321
// It adds various headers to enforce browser security features.
261
322
func secureHeaders (next http.Handler ) http.Handler {
262
- // Content-Security-Policy disables loading certain content types and can prevent XSS injections.
263
- // This site helps eval your policy for syntax and other common issues: https://csp-evaluator.withgoogle.com/
264
- // If we ever want to render something like a PDF, we need to adjust "object-src"
265
- //
266
- // The list of CSP options: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/default-src
267
- cspSrcs := CSPDirectives {
268
- // All omitted fetch csp srcs default to this.
269
- CSPDirectiveDefaultSrc : {"'self'" },
270
- CSPDirectiveConnectSrc : {"'self' ws: wss:" },
271
- CSPDirectiveChildSrc : {"'self'" },
272
- CSPDirectiveScriptSrc : {"'self'" },
273
- CSPDirectiveFontSrc : {"'self'" },
274
- CSPDirectiveStyleSrc : {"'self' 'unsafe-inline'" },
275
- // object-src is needed to support code-server
276
- CSPDirectiveObjectSrc : {"'self'" },
277
- // blob: for loading the pwa manifest for code-server
278
- CSPDirectiveManifestSrc : {"'self' blob:" },
279
- CSPDirectiveFrameSrc : {"'self'" },
280
- // data: for loading base64 encoded icons for generic applications.
281
- // https: allows loading images from external sources. This is not ideal
282
- // but is required for the templates page that renders readmes.
283
- // We should find a better solution in the future.
284
- CSPDirectiveImgSrc : {"'self' https: https://cdn.coder.com data:" },
285
- CSPDirectiveFormAction : {"'self'" },
286
- CSPDirectiveMediaSrc : {"'self'" },
287
- // Report all violations back to the server to log
288
- CSPDirectiveReportURI : {"/api/v2/csp/reports" },
289
- CSPFrameAncestors : {"'none'" },
290
-
291
- // Only scripts can manipulate the dom. This prevents someone from
292
- // naming themselves something like '<svg onload="alert(/cross-site-scripting/)" />'.
293
- // "require-trusted-types-for" : []string{"'script'"},
294
- }
295
-
296
- var csp strings.Builder
297
- for src , vals := range cspSrcs {
298
- _ , _ = fmt .Fprintf (& csp , "%s %s; " , src , strings .Join (vals , " " ))
299
- }
300
-
301
323
// Permissions-Policy can be used to disabled various browser features that we do not use.
302
324
// This can prevent an embedded iframe from accessing these features.
303
325
// If we support arbitrary iframes such as generic applications, we might need to add permissions
@@ -322,15 +344,11 @@ func secureHeaders(next http.Handler) http.Handler {
322
344
}, ", " )
323
345
324
346
return secure .New (secure.Options {
325
- // Set to ContentSecurityPolicyReportOnly for testing, as all errors are printed to the console log
326
- // but are not enforced.
327
- ContentSecurityPolicy : csp .String (),
328
-
329
347
PermissionsPolicy : permissions ,
330
348
331
349
// Prevent the browser from sending Referer header with requests
332
350
ReferrerPolicy : "no-referrer" ,
333
- }).Handler (next )
351
+ }).Handler (cspHeaders ( next ) )
334
352
}
335
353
336
354
// htmlFiles recursively walks the file system passed finding all *.html files.
0 commit comments