using afIocConfig::Configusing afIocConfig::ConfigSourceusing afBedSheet::HttpRequestusing afBedSheet::HttpResponse** Guards against Cross Site Scripting (XSS) by setting an 'Content-Security-Policy' HTTP response header that tells browsers to restrict where content can be loaded from.**** Content-Security-Policy: default-src 'self'; font-src 'self' https://fonts.googleapis.com/; object-src 'none'**** See `https://content-security-policy.com/` and [Content-Security-Policy on MDN]`https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy` for details.**** By default, Sleep Safe sets the following content directives:**** Content-Security-Policy:** default-src 'self';** base-uri 'self';** form-action 'self';** frame-ancestors 'self';** object-src 'none';** report-uri /_sleepSafeCspViolation;**** Which essentially locks all content down to that served by the BedSheet server and disables object tags.**** SleepSafe also sets up a BedSheet Route ('report-uri') that browsers can report violations to.** The default implementation logs a pretty printed version of the report JSON.**** The default strategy is a good base to start with. You can then upgrade the directives as and when you need to.** Although beware of inline scripts and style tags, as these will also be disabled. See [Implementing Content Security Policy]`https://hacks.mozilla.org/2016/02/implementing-content-security-policy/` for details.**** The reporting mechanism is good for development, but you may want to turn it off for production as browser add-ons can** cause violations, flooding your server.******** Ioc Configuration** ********************* table:** afIocConfig Key Value** --------------------------- ------------** 'afSleepSafe.csp.XXXX' Any config starting with 'afSleepSafe.csp.' (note the trailing dot) is taken as a CSP directive and used as is. Set to 'null' to remove a directive.** 'afSleepSafe.cspReportOnly' If 'true' then the 'Content-Security-Policy-Report-Only' header is set, which doesn't block anything but still sends violation reports. Defaults to 'false'.** 'afSleepSafe.cspReportFn' The reporting function (immutable) that's invoked with the browsers violation JSON. Set to 'null' to disable report handling and the default BedSheet route.**** Example:**** syntax: fantom** @Contribute { serviceType=ApplicationDefaults# }** Void contributeAppDefaults(Configuration config) {** // configure CSP** config["afSleepSafe.cspReportOnly"] = true** config["afSleepSafe.cspReportFn"] = |Str:Obj? reportJson| { echo(reportJson) }.toImmutable**** // set CSP directives** config["afSleepSafe.csp.default-src"] = "'none'"** config["afSleepSafe.csp.font-src"] = "'self' https://fonts.googleapis.com/"** }**** To prevent CSP violations from being logged on the server, remove either (or both) of the following ApplicationDefaults:** ** syntax: fantom** config.remove("afSleepSafe.csp.report-uri")** config.remove("afSleepSafe.cspReportFn")** ** To disable CSP, remove this class from the 'SleepSafeMiddleware' configuration:**** syntax: fantom** @Contribute { serviceType=SleepSafeMiddleware# }** Void contributeSleepSafeMiddleware(Configuration config) {** config.remove(CspGuard#)** }**constclass CspGuard : Guard {privateconst Str? csp @Config { id="afSleepSafe.cspReportOnly"}privateconst Bool reportOnly** The 'Content-Security-Protection' directives that get passed to the browserconst Str:Str directives @NoDocoverrideconst Str protectsAgainst := "XSS"privatenew make(ConfigSource configSrc, |This| f){ f(this) directives := Str:Str[:] configSrc.config.each |val, key| {if(key.startsWith("csp.") || key.startsWith("afSleepSafe.csp.")){if(key.startsWith("afSleepSafe.")) key = key["afSleepSafe.".size..-1]if(key.startsWith("csp.")) key = key["csp.".size..-1]if(val != null) directives[key] = val.toStr}} directives2 := Str:Str[:]{it.ordered = true} directives.keys.sort.each { directives2[it] = directives[it]}this.directives = directives2this.csp = directives2.join("; ") |val, key| {"${key} ${val}"}.trimToNull} @NoDocoverride Str? guard(HttpRequest httpReq, HttpResponse httpRes){if(csp != null){// set the headers at the start of the request so other code may add or manipulate itif(reportOnly) httpRes.headers["Content-Security-Policy-Report-Only"] = cspelse httpRes.headers["Content-Security-Policy"] = csp// don't bother setting the CSP header for non-HTML files// https://stackoverflow.com/questions/48151455/for-which-content-types-should-i-set-security-related-http-response-headers httpRes.onCommit |->| { contentType := httpRes.headers.contentType?.noParams?.toStr?.lowerif(contentType == "text/html" || contentType == "application/xhtml+xml")return// if it's not a HTML page, then remove the headersif(reportOnly){ httpRes.headers["Content-Security-Policy-Report-Only"] = null}else{ httpRes.headers["Content-Security-Policy"] = null}}}returnnull}}