Developing CSP-safe applications
When the system administrator enables Enable Strict Content Security Policy (see General, Integrations, and Security tabs), the browser will refuse to execute scripts that do not match a per-response nonce, and will block runtime code generation. This page lists the patterns app authors need to avoid and what to use instead.
Why strict CSP matters
With strict CSP, the server sets script-src to 'nonce-<random>'
'strict-dynamic'. This has the following effects:
-
Inline
<script>tags that the platform does not insert itself are blocked, because they have no nonce. -
Inline event-handler attributes (
onclick="…",onchange="…", and so on) are blocked, because CSP treats them as inline scripts. -
eval()andnew Function()are blocked. -
'unsafe-inline'and'unsafe-eval'are not present, and host whitelisting via the CSP whitelist setting does not extendscript-src(onlydefault-src,img-src,frame-src, andstyle-src).
The platform handles its own pages (Cockpit, launchpads, login, Swagger UI,
single sign-on redirect pages, and compiled apps from the App Designer) by
injecting a fresh nonce into every <script> it emits. Code that you write
inside app scripts, event handlers, and HTML controls runs after that and
does not benefit from the nonce automatically.
Do not use inline event-handler attributes
CSP blocks onclick, onchange, oninput, and similar attributes when set
in HTML.
Do not do this:
<input type="file" id="favUploader" accept=".csv" onchange="uploadFav(event)" />
Do this instead — declare the markup without the handler, then wire it up in the app’s Init script:
<input type="file" id="favUploader" accept=".csv" />
sap.n.Shell.attachBeforeDisplay(localAppID, function (data) {
const uploader = document.getElementById("favUploader");
if (uploader && !uploader.dataset.listenerAttached) {
uploader.addEventListener("change", uploadFav, { once: true });
uploader.dataset.listenerAttached = "true";
}
});
For one-shot interactions such as a file upload input, { once: true } is
recommended. It removes the listener after the first invocation and avoids
double-handling if the control is re-rendered.
|
Do not use eval or new Function
Both are blocked. The common case is user-defined formatters in tile groups, launchpad customization, or dynamic templating.
Do not do this:
const formatter = new Function("value", "return '$' + value");
Use the platform-provided CSP-safe helper instead:
const formatter = neptune.Utils.compileFunctionGlobal(["value"], "return '$' + value");
compileFunctionGlobal produces an equivalent function in a way that the
platform whitelists for strict CSP.
Do not put hand-written <script> tags into HTML controls
A <script> element that you place into the markup of an HTML control is
not nonced by the platform and will be blocked. Move the code into the
app’s Init script or into a dedicated event handler instead of embedding
it in markup.
Inline styles are still permitted
style-src keeps 'unsafe-inline', so under strict CSP:
-
<style>…</style>blocks andstyle="…"attributes in HTML controls work normally. -
Stylesheets loaded from external hosts still require the host to be on the CSP whitelist.
|
Inline styles being permitted is therefore expected and acceptable from a
penetration-testing standpoint; the security-relevant restriction is on
|
Third-party scripts and iframes
Adding a host to the CSP whitelist does not let its scripts run when
strict CSP is enabled — script-src is locked to nonce and
'strict-dynamic'.
-
For scripts, use the
'strict-dynamic'behaviour: a trusted (nonced) script may dynamically inject another<script>element, and that script is then allowed to load further scripts regardless of host. This is the recommended pattern for loading third-party libraries at runtime. -
For iframes, add the host to the CSP whitelist and embed the frame with a standard
<iframe>tag — frames are governed byframe-src, which the whitelist does extend. -
For images, fonts, and data fetches, add the host to the CSP whitelist.
Hosts that are always allowed
You do not need to add the following hosts to the CSP whitelist; they are included by default:
-
openui5.hana.ondemand.com,ui5.sap.com— UI5 CDN -
template.neptune-software.com,portal.neptune-software.com,wss://portal.neptune-software.com— Neptune template gallery and Neptune DXP Portal -
requirejs.org -
registry.npmjs.com,registry.npmjs.org— npm package search in the Script Editor -
www.gravatar.com -
validator.swagger.io
Behavior differences under strict CSP
-
ABAP support in the Script Editor is disabled, because the underlying language service relies on dynamic code generation.
-
UI5 libraries are preloaded by the server rather than fetched on demand.
-
CSP is applied only to responses with
Content-Type: text/html. JSON, OData, and binary endpoints are unaffected.
|
As of now, the Neptune DXP Marketplace does not work when strict CSP is enabled. This may change in a future release. If you need to install Marketplace items, we recommend installing them on a development system (with strict CSP disabled) and then deploying them to your production system. |
Testing your changes
-
Enable Enable Strict Content Security Policy on a non-production system, restart the server, and reload the app you are working on.
-
Open the browser developer tools console. CSP violations are reported as
Refused to execute inline script…orRefused to evaluate a string as JavaScript…, together with the source location of the offending code.