Security: Content Security Policy (CSP)
Created by Gustaf Neumann, last modified by Gustaf Neumann 24 Aug 2020, at 01:40 PM
Starting with version 5.9.1, OpenACS supports Content Security Policies (CSP), which is a means to secure websites against a range of Cross Side Scripting (XSS) attacks. In short, a CSP allows a developer to deactivate unneeded features in the browser of the client to provide there a sandbox with the minimum required capabilities. The CSP can allow e.g. just to retrieve .js files just form certain sites, or it can disallow script tags within the page, which might be injected by an attacker (for a more detailed introduction and tutorial, see CSP Reference, Google Developer Guide for CSP).
In general, a CSP defines the rules what should be allowed in a page. This could be done static for the whole page, but this means that the CSP rules must allow everything which is needed on a page with the highest requirements (e.g. a page with a richtext editor needs probably a script-src 'unsafe-eval'
directive). This could render CSP pretty useless.
Therefore, OpenACS supports a CSP generator, which generates a CSP rule-set for every page dynamically based on the requirements of the page. A web developer can specify the requirements of a page/proc with the command security::csp::require. For example, the current OpenACS theme uses in its plain-master the following directives.
security::csp::require img-src ipv6-test.com
security::csp::require style-src maxcdn.bootstrapcdn.com security::csp::require script-src maxcdn.bootstrapcdn.com
security::csp::require font-src 'self' security::csp::require font-src maxcdn.bootstrapcdn.com
Based on the directives of the pages and the directives of the master templates, the security policy of the pages is built (typically in the blank-master). For example, the content security policy of the start page of OpenACS is
default-src 'self'; font-src 'self' maxcdn.bootstrapcdn.com data:; img-src ipv6-test.com 'self'; report-uri
/SYSTEM/csp-collector.tcl; script-src maxcdn.bootstrapcdn.com 'self' 'nonce-49DBB4A924EA648C3025F7DD8C2553DC0EC700D1'
; style-src maxcdn.bootstrapcdn.com 'self' 'unsafe-inline';
With this CSP, openacs.org gets an A+ rating from securityheaders.io.
Deactivating CSP for a Site
Per default, the content security policies are turned on. All packages of the oacs-5-9 branch can be used with the enabled content security policies. However, when a website contains legacy code using JavaScript, for which no content security policies are defined, this will result into non-functioning pages. Therefore, a website administrator can set the package parameter CSPEnabledP (in the package parameters of ACS Kernel in "security" section) to "0" to deactivate the CSP.
For Developers
In order to make old packages (not included in the oacs-5-9 branch) or newly developed packages CSP compliant, one should be aware that all inline code is considered harmful. This includes <script>
elements, but also "javascript:"
URIs or on*
event handlers.
<script>
Elements
The CSP guidelines recommend to replace the such elements in favor of JavaScript files obtained from the same source as the page itself. However, this is not always practical, especially, when JavaScript is generated dynamically. In such cases, two approaches are possible to make the script tag acceptable (without allowing all scripts on the page). CSP 2 offers the ability to add nonces or cryptographic hashes to secure this elements. OpenACS supports the first approach.
A nonce value is essentially a one-time value which can't be predicted by an attacker. OpenACS generates by its security-procs such as value and saves it in a global variable ::__csp_nonce
. This can be used in the Tcl code or in an ADP page like in the following example:
<script language="JavaScript"
type="text/javascript"
<if @::__csp_nonce@ not nil> nonce="@::__csp_nonce;literal@"</if>
>
...
</script>
Event handlers and "javascript:
" URI
Most work are probably changes concerning event handlers (e.g. onclick
, onblur
, ...) and "javascript:
" URIs (having "javascript" in the protocol part of the URI). In general, such code pieces must be refactored (see e.g. 1 or 2 for examples).
OpenACS 5.9.1 offers to ease this process the function template::add_event_listener, which can be used to register event handlers in a compliant fashion either per HTML ID or per CSS class (see cal-item-new.tcl or in forums/lib/message/row2.tcl for examples, how add_event_listener can be used).