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