Configuring Content Security Policy Headers
Modern browsers use Content Security Policy HTTP response headers to enhance web pages’ security to mitigate certain types of attacks (like Cross-Site Scripting or data injection). You can enable CSP on Liferay to send the configured headers on each HTTP request.
CSP policies have many options. It is best to understand your users’ needs and come up with a policy to suit their requirements. After enabling CSP headers, they’re enforced by the browsers. Visit the links below to learn more about how browsers handle CSP headers:
This feature is currently behind a beta feature flag. See Beta Feature Flags for more information. Configuring an unsupported content security policy can cause your instance to malfunction.
Content Security Policy Directives and Values
Content Security Policies take the form of key-value pairs. The keys are directives, and they can have values. Using directives and values, you can form a robust policy to protect web applications against a variety of threats.
Directives: Directives specify the resources (scripts, stylesheets, images, etc.) a browser can load or execute on a web page. Below are examples of some commonly used directives.
Directive | Description |
---|---|
default-src | Specifies the default source for content types not explicitly defined by other directives. |
base-uri | Specifies the base URL for resolving relative URLs. |
connect-src | Specifies the sources to which you can make network requests. |
img-src | Specifies the sources from where you can load images. |
script-src | Specifies the sources from where you can load JavaScript and execute them. |
script-src-attr | Specifies the sources from where you can load inline script event handlers like onClick. |
style-src | Specifies the sources from where you can load stylesheets. |
Values: Values specify the approved origins to load resources from. Below are examples of some commonly used values. In addition to these, you can also specify URLs.
Value | Description |
---|---|
self | Allows loading and execution of resources from the same origin. |
unsafe-eval | Allows execution of code generated by eval() and other unsafe methods. |
unsafe-inline | Allows the inclusion of inline stylesheets, scripts, inline event handlers, etc. |
[$NONCE$] | Allows execution of scripts or loading of stylesheets with a specific nonce value generated by the server. |
strict-dynamic | Allows execution of scripts from trusted sources. Scripts included by loaders from a trusted script are not blocked. |
none | Blocks execution of the specified directive from all sources. |
It’s important to note that while unsafe-eval
and unsafe-inline
provide flexibility in terms of code execution and styling, they come with increased security risks. Liferay currently cannot support a fully unsafe-
free CSP due to certain limitations. See Current Limitations of CSP for more information.
While strict-dynamic
simplifies CSP configuration and reduces the need for nonce propagation, it may enlarge the attack surface by allowing any script loaded by trusted scripts to execute.
Alternatively, you can send nonces from the server to the client, ensuring that dynamically loaded scripts have the necessary nonce attribute for compliance with CSP. This approach involves proprietary mechanisms, managed by Liferay, to propagate nonces from the server to the client.
This approach provides more granular control over script loading and may be preferable in scenarios where strict control over script execution is essential. However, it requires proprietary mechanisms for nonce propagation, which may be more complex.
The choice between strict-dynamic
and nonce propagation depends on factors such as the specific threat model, risk tolerance, and operational requirements. Consider the pros and cons before implementing it in your CSP.
Configuring a Sample Content Security Policy
-
Open the Global Menu () and navigate to Control Panel → Instance Settings → Security → Content Security Policy.
-
To enable CSP headers, check the Enabled checkbox. You can enter your policy in the Content Security Policy input field and specify a number of paths to exclude (see below).
-
Enter the following policy in the Content Security Policy input field.
default-src 'self'; script-src 'self' https://trusted-cdn.example.com '[$NONCE$]'; style-src 'self' https://trusted-cdn.example.com '[$NONCE$]' base-uri 'self';
This sample content security policy allows resources to load only from the same origin self
and from the trusted content delivery network https://trusted-cdn.example.com
. It also includes the nonce '[$NONCE$]'
for scripts and stylesheets to secure their integrity and prevent unauthorized script execution. The base-url 'self'
value instructs the browser to allow loading resources only from the same origin as the document.
- Click Update.
Content Security Policy: Specify the content security policy to enforce. The value entered here appears as the value for the Content-Security-Policy
HTTP header. You can add a nonce by using the placeholder '[$NONCE$]'
in your content security policy. The placeholder is replaced with a generated nonce for the tags you specify.
Excluded Paths: Paths that start with the value added here are excluded from the content security policy. You can add multiple paths to exclude by clicking the button or remove them using the button.
CSP configuration is available at all scopes. For the system scope, go to Control Panel → System Settings → Security → Content Security Policy. For the site scope, open the site menu and go to Configuration → Site Settings → Security → Content Security Policy.
Current Limitations of CSP
This feature is still in beta and has the following limitations.
-
Your
script-src
directive must have theunsafe-eval
andunsafe-inline
values defined. The first is to support Webpack, because Liferay uses it to bundle code, and the second is to support CKEditor 4, which is the only supported WYSIWYG editor. -
Your
style-src
directive must have theunsafe-inline
value, because Liferay has both inline style attributes and also adds stylesheets to the<head>
tag using scripts. -
Your
script-src-attr
directive must have theunsafe-inline
value, because Liferay contains inline event listeners within HTML elements.
Content Security Policies work best with SPA disabled. To disable it, add javascript.single.page.application.enabled=false
to your portal-ext.properties file.
Site level configuration panel and common pages (such as the 404 page) belong to the instance, so they use the instance level CSP headers.