Skip to content

Commit f2bb2e4

Browse files
authored
fix: validate client before adding to url parameters (#4613)
* fix: validate client before adding to url parameters validate client before adding to url parameters * fix: correction correction * test: additional test additional test * fix: review comment review comment * test: adjustment adjustment
1 parent c912fd0 commit f2bb2e4

3 files changed

Lines changed: 51 additions & 3 deletions

File tree

.changeset/sparkly-clocks-laugh.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@sap-ux-private/preview-middleware-client': patch
3+
---
4+
5+
Fix sonar issue 'Ensure that tainted data is validated before being used to construct a client-side request URL.' for method 'registerComponentDependencyPaths'

packages/preview-middleware-client/src/flp/init.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,9 +185,9 @@ export async function resetAppState(container: typeof sap.ushell.Container): Pro
185185
export async function registerComponentDependencyPaths(appUrls: string[], urlParams: URLSearchParams): Promise<void> {
186186
const libs = await getManifestLibs(appUrls);
187187
if (libs && libs.length > 0) {
188-
let url = '/sap/bc/ui2/app_index/ui5_app_info?id=' + libs;
188+
let url = '/sap/bc/ui2/app_index/ui5_app_info?id=' + encodeURIComponent(libs);
189189
const sapClient = urlParams.get('sap-client');
190-
if (sapClient?.length === 3) {
190+
if (sapClient?.length === 3 && /^\d+$/.test(sapClient)) {
191191
url = url + '&sap-client=' + sapClient;
192192
}
193193
const response = await fetch(url);

packages/preview-middleware-client/test/unit/flp/init.test.ts

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ describe('flp/init', () => {
9797

9898
beforeEach(() => {
9999
loaderMock.mockReset();
100+
fetchMock.mockReset();
100101
});
101102

102103
test('single app, no reuse libs', async () => {
@@ -161,6 +162,48 @@ describe('flp/init', () => {
161162
expect(error).toEqual('Error');
162163
}
163164
});
165+
166+
describe('test "sap-client" param validation', () => {
167+
const sapClientParamTests = [
168+
{
169+
name: 'Valid client',
170+
value: '001',
171+
expected: '/sap/bc/ui2/app_index/ui5_app_info?id=test.lib%2C&sap-client=001'
172+
},
173+
{
174+
name: 'Client contains non number',
175+
value: 'T12',
176+
expected: '/sap/bc/ui2/app_index/ui5_app_info?id=test.lib%2C'
177+
},
178+
{
179+
name: 'Client more than 3 symbols',
180+
value: '4444',
181+
expected: '/sap/bc/ui2/app_index/ui5_app_info?id=test.lib%2C'
182+
},
183+
{
184+
name: 'Client less than 3 symbols',
185+
value: '44',
186+
expected: '/sap/bc/ui2/app_index/ui5_app_info?id=test.lib%2C'
187+
}
188+
];
189+
test.each(sapClientParamTests)('$name', async ({ value, expected }) => {
190+
const manifest = JSON.parse(JSON.stringify(testManifest)) as typeof testManifest;
191+
manifest['sap.ui5'].dependencies.libs['test.lib'] = {};
192+
fetchMock.mockResolvedValueOnce({ json: () => manifest });
193+
fetchMock.mockResolvedValueOnce({
194+
json: () => ({
195+
'test.lib': {
196+
dependencies: [{ url: '~url', type: 'UI5LIB', componentId: 'test.lib.component' }]
197+
}
198+
})
199+
});
200+
const params = new URLSearchParams();
201+
params.set('sap-client', value);
202+
await registerComponentDependencyPaths(['/'], params);
203+
expect(loaderMock).toHaveBeenCalledWith({ paths: { 'test/lib/component': '~url' } });
204+
expect(fetchMock).toHaveBeenCalledWith(expected);
205+
});
206+
});
164207
});
165208

166209
describe('resetAppState', () => {
@@ -388,7 +431,7 @@ describe('flp/init', () => {
388431
callback({}); // WorkspaceConnector
389432
return;
390433
}
391-
434+
392435
await callback(() => Promise.reject('Reload triggered'));
393436
resolve(undefined);
394437
});

0 commit comments

Comments
 (0)