diff --git a/docs/2-advanced/01-configuration.md b/docs/2-advanced/01-configuration.md
index 97263659c249..d3ad5792ae53 100644
--- a/docs/2-advanced/01-configuration.md
+++ b/docs/2-advanced/01-configuration.md
@@ -283,6 +283,13 @@ Example:
```
+*Note:* For security reasons, setting the `themeRoot` parameter via URL must be explicitly allowed by calling:
+
+```
+import { allowThemeRootUrl } from "@ui5/webcomponents-base/dist/config/ThemeRoot.js";
+allowThemeRootUrl(true);
+```
+
## Configuration Script
diff --git a/packages/base/cypress/specs/ConfigurationURL.cy.tsx b/packages/base/cypress/specs/ConfigurationURL.cy.tsx
index 22078bef0566..99f2fc6bf5ce 100644
--- a/packages/base/cypress/specs/ConfigurationURL.cy.tsx
+++ b/packages/base/cypress/specs/ConfigurationURL.cy.tsx
@@ -1,6 +1,7 @@
import { internals } from "../../src/Location.js";
import TestGeneric from "../../test/test-elements/Generic.js";
import { resetConfiguration } from "../../src/InitialConfiguration.js";
+import { allowThemeRootUrl } from "../../src/config/ThemeRoot.js";
import { getLanguage } from "../../src/config/Language.js";
import { getCalendarType } from "../../src/config/CalendarType.js";
import { getTheme } from "../../src/config/Theme.js";
@@ -16,6 +17,10 @@ describe("Some settings can be set via SAP UI URL params", () => {
return searchParams;
});
+ cy.then(() => {
+ return allowThemeRootUrl(true);
+ });
+
cy.then(() => {
return resetConfiguration(true);
});
diff --git a/packages/base/src/InitialConfiguration.ts b/packages/base/src/InitialConfiguration.ts
index a8e3b1ad448f..d210816e8201 100644
--- a/packages/base/src/InitialConfiguration.ts
+++ b/packages/base/src/InitialConfiguration.ts
@@ -8,6 +8,7 @@ import AnimationMode from "./types/AnimationMode.js";
import type CalendarType from "./types/CalendarType.js";
import { resetConfiguration as resetConfigurationFn } from "./config/ConfigurationReset.js";
import { getLocationSearch } from "./Location.js";
+import { themeRootUrlAllowed } from "./config/ThemeRoot.js";
let initialized = false;
@@ -56,6 +57,10 @@ const getTheme = () => {
const getThemeRoot = () => {
initConfiguration();
+ if (!themeRootUrlAllowed() && initialConfig.themeRoot) {
+ console.warn("Setting sap-ui-themeRoot via URL must be explicitly allowed by calling allowThemeRootUrl(true); The provided sap-ui-themeRoot was ignored."); // eslint-disable-line
+ initialConfig.themeRoot = undefined;
+ }
return initialConfig.themeRoot;
};
diff --git a/packages/base/src/config/ThemeRoot.ts b/packages/base/src/config/ThemeRoot.ts
index 2e621d10020b..aa99e8f7d208 100644
--- a/packages/base/src/config/ThemeRoot.ts
+++ b/packages/base/src/config/ThemeRoot.ts
@@ -4,6 +4,7 @@ import { getThemeRoot as getConfiguredThemeRoot } from "../InitialConfiguration.
import { getTheme } from "./Theme.js";
import { attachConfigurationReset } from "./ConfigurationReset.js";
+let urlAllowed = false;
let currThemeRoot: string | undefined;
attachConfigurationReset(() => {
@@ -70,8 +71,18 @@ const attachCustomThemeStylesToHead = async (theme: string): Promise => {
await createLinkInHead(formatThemeLink(theme), { "sap-ui-webcomponents-theme": theme });
};
+const allowThemeRootUrl = (enable: boolean) => {
+ urlAllowed = enable;
+};
+
+const themeRootUrlAllowed = () => {
+ return urlAllowed;
+};
+
export {
getThemeRoot,
setThemeRoot,
attachCustomThemeStylesToHead,
+ allowThemeRootUrl,
+ themeRootUrlAllowed,
};
diff --git a/packages/cypress-internal/src/commands.ts b/packages/cypress-internal/src/commands.ts
index fd5ad18546ea..8590278de494 100644
--- a/packages/cypress-internal/src/commands.ts
+++ b/packages/cypress-internal/src/commands.ts
@@ -1,10 +1,12 @@
import { mount } from '@ui5/cypress-ct-ui5-webc';
+// @ts-ignore
import { renderFinished } from '@ui5/webcomponents-base/dist/Render.js';
import "cypress-real-events";
import '@cypress/code-coverage/support';
import "./acc_report/support.js";
import "./helpers.js";
+// @ts-ignore
Cypress.Commands.add('waitRenderFinished', () => {
return cy.wrap(renderFinished(), { log: false });
});
diff --git a/packages/main/src/bundle.common.bootstrap.ts b/packages/main/src/bundle.common.bootstrap.ts
index bfe51ae57a00..57f37d28e428 100644
--- a/packages/main/src/bundle.common.bootstrap.ts
+++ b/packages/main/src/bundle.common.bootstrap.ts
@@ -61,7 +61,7 @@ import { sanitizeHTML, URLListValidator } from "@ui5/webcomponents-base/dist/uti
import { getAnimationMode, setAnimationMode } from "@ui5/webcomponents-base/dist/config/AnimationMode.js";
import { getTheme, setTheme, isLegacyThemeFamily } from "@ui5/webcomponents-base/dist/config/Theme.js";
-import { getThemeRoot, setThemeRoot } from "@ui5/webcomponents-base/dist/config/ThemeRoot.js";
+import { getThemeRoot, setThemeRoot, allowThemeRootUrl } from "@ui5/webcomponents-base/dist/config/ThemeRoot.js";
import { getTimezone, setTimezone } from "@ui5/webcomponents-base/dist/config/Timezone.js";
import { getLanguage, setLanguage } from "@ui5/webcomponents-base/dist/config/Language.js";
import getEffectiveIconCollection from "@ui5/webcomponents-base/dist/asset-registries/util/getIconCollectionByTheme.js";
@@ -80,6 +80,8 @@ import * as defaultTexts from "./generated/i18n/i18n-defaults.js";
setRuntimeAlias("UI5 Web Components Playground");
+allowThemeRootUrl(true);
+
// @ts-ignore
window.sanitizeHTML = sanitizeHTML;
// @ts-ignore