diff --git a/content/en/docs/deployment/mendix-cloud-deploy/environments-details.md b/content/en/docs/deployment/mendix-cloud-deploy/environments-details.md index c994594dd29..7add31038c8 100644 --- a/content/en/docs/deployment/mendix-cloud-deploy/environments-details.md +++ b/content/en/docs/deployment/mendix-cloud-deploy/environments-details.md @@ -323,6 +323,10 @@ document.cookie = "originURI=/login.html" + (window.location.protocol === "https A Content Security Policy informs the client (browser) where your page loads resources from. Setting this can make your app more secure by declaring trusted sources for your resources. For more information, see the W3C recommendation [Content Security Policy Level 2](https://www.w3.org/TR/CSP2/). +{{% alert color="info" %}} +For full CSP support including nonce-based CSP, use the [Headers](/refguide/configuration/#headers) custom runtime setting instead of the HTTP Headers UI. The custom runtime setting method is recommended as it provides more comprehensive CSP capabilities. For detailed implementation guidance, see [Content Security Policy](/howto/security/csp/). +{{% /alert %}} + The process for setting a full content security policy depends on what your app does. However, a starting point that declares the content security policy that works with a basic Mendix app is given below: ```text diff --git a/content/en/docs/howto/security/csp.md b/content/en/docs/howto/security/csp.md index 10fb173ebf6..133ee695eef 100644 --- a/content/en/docs/howto/security/csp.md +++ b/content/en/docs/howto/security/csp.md @@ -174,6 +174,160 @@ After redeploying your app locally, it should function as normal. If your app do After you finish testing locally, remember to remove the line of code in the `head` tag. -### Enabling the Header in the Cloud +## CSP Support in Java Request Handlers -To enable the header in the cloud, follow the instructions in the [HTTP Headers](/developerportal/deploy/environments-details/#http-headers) section of *Environment Details*. +If you are developing Marketplace modules or custom Java actions that include request handlers, you may need to implement CSP support to ensure compatibility with strict CSP policies. This includes support for CSP Level 2+ features like nonces for inline scripts and styles. + +{{% alert color="info" %}} +CSP support is only relevant for request handlers that serve static content such as HTML pages, not for API endpoints that return JSON or other data formats. +{{% /alert %}} + +This section describes how to properly handle CSP headers in your Java request handlers when serving HTML content. + +### Available CSP APIs + +Mendix provides two APIs for CSP support in Java request handlers: + +#### IMxRuntimeResponse Methods + +The `IMxRuntimeResponse` interface provides basic CSP methods: + +* `addContentSecurityPolicyHeader()` - Adds the Content-Security-Policy header as configured in the application +* `getNonce()` - Returns a uniquely generated secure nonce for the response that can be used in CSP directives +* `addHeader(String key, String value)` - Adds a custom header to the response + +#### CspHelper Interface (Recommended) + +The `CspHelper` interface provides additional utility methods for more sophisticated CSP handling: + +* `getTemplate()` - Get the template used for the Content-Security-Policy header value +* `getNonce(IMxRuntimeResponse response)` - Get the generated nonce of the current HTTP response +* `hasNonce(IMxRuntimeResponse response)` - Returns true if the configured CSP template contains the `{{ NONCE }}` placeholder, for example: `Content-Security-Policy: script-src 'nonce-{{ NONCE }}'` +* `addHeader(IMxRuntimeResponse response)` - Add Content-Security-Policy header to the response using the configured template + +### Example Implementation + +Here's how to implement CSP support in a Java request handler using the `CspHelper`: + +```java +package your.module.requesthandlers; + +import com.mendix.externalinterface.connector.RequestHandler; +import com.mendix.m2ee.api.IMxRuntimeRequest; +import com.mendix.m2ee.api.IMxRuntimeResponse; +import com.mendix.http.CspHelper; +import com.mendix.core.Core; + +public class YourRequestHandler extends RequestHandler { + + @Override + protected void processRequest(IMxRuntimeRequest request, IMxRuntimeResponse response, String path) throws Exception { + try { + // Add the configured CSP header from the application + Core.csp().addHeader(response); + + // Set response content type + response.setContentType("text/html"); + + // Generate your response content with conditional nonce support + String htmlContent = generateHtmlWithCSP(response); + + // Write the response + response.getWriter().write(htmlContent); + + } catch (Exception e) { + logger.error("Error processing request: " + e.getMessage(), e); + response.setStatus(IMxRuntimeResponse.INTERNAL_SERVER_ERROR); + response.sendError("Internal server error"); + } + } + + private String generateHtmlWithCSP(IMxRuntimeResponse response) { + StringBuilder html = new StringBuilder(); + html.append("\n"); + html.append("\n"); + html.append("\n"); + html.append(" Your Module\n"); + + // Only use nonce if it's configured in the CSP template + if (Core.csp().hasNonce(response)) { + String nonce = Core.csp().getNonce(response); + html.append(" \n"); + } else { + // Alternative approach when nonce is not configured + html.append(" \n"); + } + + html.append("\n"); + html.append("\n"); + html.append("

Your Module Content

\n"); + html.append(" \n"); + html.append("\n"); + html.append("\n"); + + return html.toString(); + } +} +``` + +### Best Practices for CSP in Request Handlers + +When implementing CSP support in your request handlers, follow these best practices: + +1. **Use CspHelper for conditional nonce support** - Always check if nonce is configured before using it: + ```java + if (Core.csp().hasNonce(response)) { + String nonce = Core.csp().getNonce(response); + // Use nonce for inline content + } else { + // Use external resources or alternative approach + } + ``` + +2. **Always add CSP headers** - Use `Core.csp().addHeader(response)` to ensure your module respects the application's CSP configuration when serving HTML content. + +3. **CSP is only needed for HTML content** - Only implement CSP support in request handlers that serve HTML pages. API endpoints returning JSON, XML, or other data formats do not need CSP headers. + +4. **Avoid inline scripts and styles when possible** - Prefer external files that can be loaded via `'self'` directive. + +5. **Test with strict CSP** - Test your request handlers with `default-src: 'self'` to ensure they work with the strictest CSP settings. + +### Common CSP Issues in Request Handlers + +When working with CSP in request handlers, you may encounter these common issues: + +#### Base64 Images +If your request handler generates inline Base64 images, these will be blocked by strict CSP. Consider these alternatives: +- Serving images as separate endpoints +- Using external image hosting +- Adding `data:` to `img-src` directive (less secure) + +#### Dynamic Script Generation +Avoid generating `