1

The "Site Settings" page available via "Manage Site" from the launchpad now allows enabling "Asynchronous Module Loading".

SAP Fiori launchpad Asynchronous Module Loading switch

But once it's enabled, some of the SAPUI5 applications or FLP plugins fail to start. The browser reports in the console:

Failed to execute '<JavaScript module>.js': Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "script-scr * 'unsafe-inline' data: blob:".

How is CSP related to the "Asynchronous Module Loading" setting in this case and what can we do to avoid evaluating "string as JavaScript" in UI5?

Boghyon Hoffmann
  • 17,103
  • 12
  • 72
  • 170

1 Answers1

1

Cause

If "Asynchronous Module Loading" is activated, not only does SAP Fiori launchpad (FLP) bootstrap SAPUI5 with data-sap-ui-async="true" but serves also its HTML document with the content-security-policy (CSP) response header that contains a set of CSP directives omitting unsafe-eval in script-src. Hence, UI5 applications and FLP plugins that initiate calling eval (and thus violating the CSP) won't be processed by the browser. In the future, stricter CSP directives might apply such as the script-src omitting unsafe-inline additionally.

In the legacy UI5 code, eval is called typically due to the application synchronously fetching JS modules via deprecated APIs. For other causes, see the table below.

Resolution

It is highly recommended to keep the "Asynchronous Module Loading" setting enabled which improves the overall UI5 performance in FLP (unblocked main thread) and security (stricter CSP).

UI5 has already deprecated legacy/synchronous APIs and - with the 1.96 release - largely improved the support for strict CSP. UI5 content owners should adjust their code accordingly:

❌ UI5 content violating CSP ✅ Making the UI5 content more CSP-compliant
Application's HTML document bootstrapping SAPUI5 without data-sap-ui-async="true" or with the debug mode activated. Ensure that the HTML document bootstraps SAPUI5 with data-sap-ui-async="true" and that no debug mode is activated unnecessarily. Review Is Your Application Ready for Asynchronous Loading?
Using inline scripts (<script>...</script>) within the application's HTML document. Use only <script src="..." ...></script> to comply with the CSP without unsafe-inline. Define the initial component declaratively via sap/ui/core/ComponentSupport.
Using deprecated APIs, factories, libs such as jQuery.sap.*, $el.outerHTML, oCore.createComponent, sap.ui.controller, sap.ui.component, sap.ui.*fragment, sap.ui.*view, sap.ui.extensionpoint, sap.ui.commons, sap.ca.scfld, sap.ushell.Container.getService, etc...

Review the documented API reference to learn about newer asynchronous APIs that replace the deprecated ones.

Use sap.ui.define or sap.ui.require to declare proper module dependencies and avoid using other sap.* global references. Same applies to custom UI5 modules.

Fetching UI5 libs and components manually but still synchronously despite using non-deprecated APIs. E.g.
/*oCore required from "sap/ui/core/Core"*/
oCore.loadLibrary("that.lib");
Review the documented API reference to learn how to enable loading such resources asynchronously. E.g. when loading a UI5 lib manually:
/*Lib required from "sap/ui/core/Lib"*/
Lib.load({ name: "that.lib" })/*since 1.118*/
oCore.loadLibrary("that.lib",/*async:*/true)
Creating the component content such as the root view, routed views, and nested views synchronously in runtime despite having them defined declaratively. Implement the "sap.ui.core.IAsyncContentCreation" marker interface in Component.js to implicitly create the component content asynchronously.

Component-preload.js / library-preload.js bundling JS modules as string due to:

  • Using the outdated standard Grunt build task. Result:
    "my/Module.js":'sap.ui.define([...'
  • Using UI5 Tooling but also global instructions before calling sap.ui.define. Result:
    • "my/Module.js":'myGlobalStuff...'
    • Warning logged by UI5 Tooling in the terminal:
      Module [...] requires top level scope and can only be embedded as a string (requires 'eval')

Generate the bundle by leveraging UI5 Tooling with e.g. ui5 build -a --clean-dest.

When defining a UI5 module, avoid global instructions but only use sap.ui.define at top-level of the JS file.

Result:
"my/Module.js":function(){//...

If it's absolutely required to keep myGlobalStuff, add globalThis.myGlobalStuff to achieve the above build result. Alternatively, you can also wrap the module definition in an IIFE but only if the top level scoped stuff is referred within that module solely, instead of globally. In UI5 library development, one can also set requiresTopLevelScope="false" to the affected raw-module within .library.

Keep in mind that this approach is not publicly documented.

Other resources that might help identifying CSP issues in UI5

UI5 Tooling middleware csp

  1. Build the app e.g. with ui5 build --all or ui5 build self-contained -a.
  2. Serve the built app from the dist folder (Refer to SAP/ui5-tooling issue #300).
    E.g. with ui5 serve --config ui5-dist.yaml.
  3. Run the app with the following URL parameter:
    index.html?sap-ui-xx-csp-policy=sap-target-level-<1 to 3>:report-only
    • The higher sap-target-level-<n>, the stricter the CSP.
    • Remove :report-only if the browser should actually apply the CSP level.
  4. Observe any CSP violation reported in the browser console.

⚠️ Currently doesn't work in combination with the custom middleware ui5-middleware-index.

Chrome DevTools

F12F1 → Select the "Show CSP Violations view" checkbox from the Experiments section.

Q&As

Documentation

For more detailed information about the current state of CSP in UI5 and which restrictions there are, see the documentation topic Content Security Policy.

Boghyon Hoffmann
  • 17,103
  • 12
  • 72
  • 170
  • If "Asynchronous Module Loading" is deactivated, would that also stop the UI5 runtime from loading preload library files based on the `manifest.json > `sap.ui5/dependencies/libs`? FYI - At the moment SAP Work Zone itself is not compatible (SAP support asked to turn it off: https://me.sap.com/notes/3323987). – Pieter May 17 '23 at 07:19
  • @Pieter Suggesting to simply disable "Asynchronous Module Loading" is highly misleading or inaccurate. You can ignore the https://me.sap.com/notes/3323987 and investigate (or create a customer incident) to learn which module is exactly violating the CSP. – Boghyon Hoffmann May 17 '23 at 11:20
  • We'll turn on async again and open a new case if any issue raises again. Regarding the preload issue, that is likely not related. I have been able to reproduce it outside of WZ and created the issue here: https://github.com/SAP/openui5/issues/3759 – Pieter May 18 '23 at 08:29
  • 1
    @Pieter The status of the KBA 3323987 is currently "To be Archieved" (and hopefully no longer discoverable since its content was not based on any evidence) – Boghyon Hoffmann Jun 12 '23 at 10:17