Background
Content Security Policy (CSP) is an added layer of security that helps to detect and mitigate certain types of attacks, including Cross-Site Scripting (XSS) and data injection attacks. These attacks are used for everything from data theft, to site defacement, to malware distribution.
Who needed it?
Administrators who care about security.
What problem does it solve?
With a strict policy an added layer of security can be provided on the client side which protects against XSS and data injection attacks. The existence of the Content Security Policy header is often a security audit requirement as well.
How can it be used by the user or developer?
The users will receive the Content Security Policy response header on each HTTP request which will be interpreted and enforced by their browsers.
Features
Our Content Security Policy implementation does two things right now:
Adds
Content-Security-PolicyHTTP header to each response. The value of this header can be configured by Administrators.Adds a random generated nonce value to each link, script and style tags according to the configured
Content-Security-PolicyHTTP header. The nonce value is freshly generated on each request and its value can be used in the policy.
Steps
Go to “System/Instance/Site Settings > Security > Content Security Policy”. Here the Administrators can enable or disable this feature, specify the policy and add URI paths which they want to be excluded from Content Security Policy modifications.
In the Content Security Policy field if the user writes [$NONCE$] it will be replaced by the generated value on each request.
Right now CSP works best with single-page-applications (a.k.a SPA) disabled which can be done by adding javascript.single.page.application.enabled=false to portal-ext.properties.
With SPA disabled, for example, the following policy can be used: default-src 'self'; base-uri 'self' 'strict-dynamic'; connect-src 'self'; img-src data: 'self' w3.org/svg/2000; script-src 'self' 'strict-dynamic' '[$NONCE$]' 'unsafe-eval'; script-src-attr 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';
Code
All relevant code is under “modules > apps > portal-security > portal-security-content-security-policy” package.
ContentSecurityPolicyConfiguration.java: Configuration class for the module.ContentSecurityPolicyConstants.java: CSP related constants are stored here.ContentSecurityPolicyFilter.java: This class does the main functionality. It’s a Servlet Filter that adds the Content-Security-Policy header to the response and intercepts the response body and rewrites all link, script and style tag to contain a nonce.
Limitations
Due to webpack bundling settings liferay.js has the following line Function(\"return this\")() which won’t work because Refused to evaluate a string as JavaScript unless we add 'unsafe-eval' to our policy. How to remove eval and Function constructor from webpack build to avoid CSP issues · Issue #6461 · webpack/webpack
We have a lot of style attributes inside HTML elements as well as some style additions to head part by scripts. For this reason we need to enable 'unsafe-inline' for styles.
Sometimes we use inline event listeners which are treated as scripts from Content Security Policy point of view so to overcome this we need to add script-src-attr 'self' 'unsafe-inline'; to our policy.
CKEditor is causing issues with the provided CSP rule but only on pages which would use it. Either the rule can be changed to script-src ‘self' 'unsafe-inline' 'unsafe-eval'; or add /group/guest/~/control_panel/manage as an excluded path but by default we wouldn’t recommend any of them. Since 7.3 CKEditor is the only supported WYSIWYG editor but Liferay is using CKEditor 4 which cannot be used without unsafe-inline (https://csplite.com/csp/test347/#nonce_dynamic).
Important notes
Site level configuration panel and common pages (such as 404 page) belong to the instance so an instance level CSP header will be used.
If you remove exclusion of /combo from config you can specify a stricter CSP such as: default-src 'self'; base-uri 'self' 'strict-dynamic'; connect-src 'self'; img-src data: 'self' w3.org/svg/2000; script-src 'self' 'strict-dynamic' '[$NONCE$]' 'unsafe-eval'; script-src-attr 'self' 'unsafe-inline'; style-src 'self' 'strict-dynamic' '[$NONCE$]'; style-src-attr 'self' 'unsafe-inline'; however bear in mind resources at /combo belong to the instance so instance CSP config values will be used.
Future plans
This update is only the first part of the CSP implementation, we are going to work on the next components in the near future:
Unsafe inline
Unsafe hashes
Unsafe expressions
Managing the
Content-Security-Policy-Report-Onlyheader with configuration


