From 0ca12790472c557fbad34406a745411d3e6f3247 Mon Sep 17 00:00:00 2001 From: Andis Redmans Date: Wed, 29 Apr 2026 11:42:33 +0300 Subject: [PATCH 1/5] fix: validate client before adding to url parameters validate client before adding to url parameters --- .changeset/sparkly-clocks-laugh.md | 5 +++ .../preview-middleware-client/src/flp/init.ts | 2 +- .../test/unit/flp/init.test.ts | 40 ++++++++++++++++++- 3 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 .changeset/sparkly-clocks-laugh.md diff --git a/.changeset/sparkly-clocks-laugh.md b/.changeset/sparkly-clocks-laugh.md new file mode 100644 index 00000000000..c604d89e089 --- /dev/null +++ b/.changeset/sparkly-clocks-laugh.md @@ -0,0 +1,5 @@ +--- +'@sap-ux-private/preview-middleware-client': patch +--- + +Fix sonar issue 'Ensure that tainted data is validated before being used to construct a client-side request URL.' for method 'registerComponentDependencyPaths' diff --git a/packages/preview-middleware-client/src/flp/init.ts b/packages/preview-middleware-client/src/flp/init.ts index 4cdc860a04b..3385e4f0124 100644 --- a/packages/preview-middleware-client/src/flp/init.ts +++ b/packages/preview-middleware-client/src/flp/init.ts @@ -187,7 +187,7 @@ export async function registerComponentDependencyPaths(appUrls: string[], urlPar if (libs && libs.length > 0) { let url = '/sap/bc/ui2/app_index/ui5_app_info?id=' + libs; const sapClient = urlParams.get('sap-client'); - if (sapClient?.length === 3) { + if (/^\d{3}$/.test(sapClient ,, ээ)) { url = url + '&sap-client=' + sapClient; } const response = await fetch(url); diff --git a/packages/preview-middleware-client/test/unit/flp/init.test.ts b/packages/preview-middleware-client/test/unit/flp/init.test.ts index 16ea22191ac..f04ddd0ec21 100644 --- a/packages/preview-middleware-client/test/unit/flp/init.test.ts +++ b/packages/preview-middleware-client/test/unit/flp/init.test.ts @@ -97,6 +97,7 @@ describe('flp/init', () => { beforeEach(() => { loaderMock.mockReset(); + fetchMock.mockReset(); }); test('single app, no reuse libs', async () => { @@ -161,6 +162,43 @@ describe('flp/init', () => { expect(error).toEqual('Error'); } }); + + describe('test "sap-client" param validation', () => { + const sapClientParamTests = [ + { + name: 'Valid client', + value: '001', + expected: '/sap/bc/ui2/app_index/ui5_app_info?id=test.lib,&sap-client=001' + }, + { + name: 'Client contains non number', + value: 'T12', + expected: '/sap/bc/ui2/app_index/ui5_app_info?id=test.lib,' + }, + { + name: 'Client more than 3 symbols', + value: '4444', + expected: '/sap/bc/ui2/app_index/ui5_app_info?id=test.lib,' + } + ]; + test.each(sapClientParamTests)('$name', async ({ value, expected }) => { + const manifest = JSON.parse(JSON.stringify(testManifest)) as typeof testManifest; + manifest['sap.ui5'].dependencies.libs['test.lib'] = {}; + fetchMock.mockResolvedValueOnce({ json: () => manifest }); + fetchMock.mockResolvedValueOnce({ + json: () => ({ + 'test.lib': { + dependencies: [{ url: '~url', type: 'UI5LIB', componentId: 'test.lib.component' }] + } + }) + }); + const params = new URLSearchParams(); + params.set('sap-client', value); + await registerComponentDependencyPaths(['/'], params); + expect(loaderMock).toHaveBeenCalledWith({ paths: { 'test/lib/component': '~url' } }); + expect(fetchMock).toHaveBeenCalledWith(expected); + }); + }); }); describe('resetAppState', () => { @@ -388,7 +426,7 @@ describe('flp/init', () => { callback({}); // WorkspaceConnector return; } - + await callback(() => Promise.reject('Reload triggered')); resolve(undefined); }); From 2d4e5dbdb1353a4c5cec0b6724ca027adfa0bc4b Mon Sep 17 00:00:00 2001 From: Andis Redmans Date: Wed, 29 Apr 2026 11:56:26 +0300 Subject: [PATCH 2/5] fix: correction correction --- packages/preview-middleware-client/src/flp/init.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/preview-middleware-client/src/flp/init.ts b/packages/preview-middleware-client/src/flp/init.ts index 3385e4f0124..7486b314f58 100644 --- a/packages/preview-middleware-client/src/flp/init.ts +++ b/packages/preview-middleware-client/src/flp/init.ts @@ -187,7 +187,7 @@ export async function registerComponentDependencyPaths(appUrls: string[], urlPar if (libs && libs.length > 0) { let url = '/sap/bc/ui2/app_index/ui5_app_info?id=' + libs; const sapClient = urlParams.get('sap-client'); - if (/^\d{3}$/.test(sapClient ,, ээ)) { + if (sapClient?.length === 3 && /^\d+$/.test(sapClient)) { url = url + '&sap-client=' + sapClient; } const response = await fetch(url); From 389d7f37370898cef3b5d73a3b023eaddf9fc178 Mon Sep 17 00:00:00 2001 From: Andis Redmans Date: Thu, 7 May 2026 08:53:14 +0300 Subject: [PATCH 3/5] test: additional test additional test --- .../preview-middleware-client/test/unit/flp/init.test.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/preview-middleware-client/test/unit/flp/init.test.ts b/packages/preview-middleware-client/test/unit/flp/init.test.ts index f04ddd0ec21..c63f83ca469 100644 --- a/packages/preview-middleware-client/test/unit/flp/init.test.ts +++ b/packages/preview-middleware-client/test/unit/flp/init.test.ts @@ -179,6 +179,11 @@ describe('flp/init', () => { name: 'Client more than 3 symbols', value: '4444', expected: '/sap/bc/ui2/app_index/ui5_app_info?id=test.lib,' + }, + { + name: 'Client less than 3 symbols', + value: '44', + expected: '/sap/bc/ui2/app_index/ui5_app_info?id=test.lib,' } ]; test.each(sapClientParamTests)('$name', async ({ value, expected }) => { From 938b9b63f9b1234b014417e4794b0f0b56fe9df3 Mon Sep 17 00:00:00 2001 From: Andis Redmans Date: Thu, 7 May 2026 09:04:28 +0300 Subject: [PATCH 4/5] fix: review comment review comment --- packages/preview-middleware-client/src/flp/init.ts | 2 +- .../preview-middleware-client/test/unit/flp/init.test.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/preview-middleware-client/src/flp/init.ts b/packages/preview-middleware-client/src/flp/init.ts index 7486b314f58..1bf6a711ee2 100644 --- a/packages/preview-middleware-client/src/flp/init.ts +++ b/packages/preview-middleware-client/src/flp/init.ts @@ -185,7 +185,7 @@ export async function resetAppState(container: typeof sap.ushell.Container): Pro export async function registerComponentDependencyPaths(appUrls: string[], urlParams: URLSearchParams): Promise { const libs = await getManifestLibs(appUrls); if (libs && libs.length > 0) { - let url = '/sap/bc/ui2/app_index/ui5_app_info?id=' + libs; + let url = '/sap/bc/ui2/app_index/ui5_app_info?id=' + encodeURIComponent(libs); const sapClient = urlParams.get('sap-client'); if (sapClient?.length === 3 && /^\d+$/.test(sapClient)) { url = url + '&sap-client=' + sapClient; diff --git a/packages/preview-middleware-client/test/unit/flp/init.test.ts b/packages/preview-middleware-client/test/unit/flp/init.test.ts index c63f83ca469..701c1d99d71 100644 --- a/packages/preview-middleware-client/test/unit/flp/init.test.ts +++ b/packages/preview-middleware-client/test/unit/flp/init.test.ts @@ -173,17 +173,17 @@ describe('flp/init', () => { { name: 'Client contains non number', value: 'T12', - expected: '/sap/bc/ui2/app_index/ui5_app_info?id=test.lib,' + expected: '/sap/bc/ui2/app_index/ui5_app_info?id=test.lib%2C' }, { name: 'Client more than 3 symbols', value: '4444', - expected: '/sap/bc/ui2/app_index/ui5_app_info?id=test.lib,' + expected: '/sap/bc/ui2/app_index/ui5_app_info?id=test.lib%2C' }, { name: 'Client less than 3 symbols', value: '44', - expected: '/sap/bc/ui2/app_index/ui5_app_info?id=test.lib,' + expected: '/sap/bc/ui2/app_index/ui5_app_info?id=test.lib%2C' } ]; test.each(sapClientParamTests)('$name', async ({ value, expected }) => { From c2c01609a9f0238ff9481505c40956ad1d14a391 Mon Sep 17 00:00:00 2001 From: Andis Redmans Date: Thu, 7 May 2026 09:05:17 +0300 Subject: [PATCH 5/5] test: adjustment adjustment --- packages/preview-middleware-client/test/unit/flp/init.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/preview-middleware-client/test/unit/flp/init.test.ts b/packages/preview-middleware-client/test/unit/flp/init.test.ts index 701c1d99d71..078f7d0361b 100644 --- a/packages/preview-middleware-client/test/unit/flp/init.test.ts +++ b/packages/preview-middleware-client/test/unit/flp/init.test.ts @@ -168,7 +168,7 @@ describe('flp/init', () => { { name: 'Valid client', value: '001', - expected: '/sap/bc/ui2/app_index/ui5_app_info?id=test.lib,&sap-client=001' + expected: '/sap/bc/ui2/app_index/ui5_app_info?id=test.lib%2C&sap-client=001' }, { name: 'Client contains non number',