diff --git a/libs/acf/util/src/lib/value.spec.ts b/libs/acf/util/src/lib/value.spec.ts index 53157c45..f605d9fb 100644 --- a/libs/acf/util/src/lib/value.spec.ts +++ b/libs/acf/util/src/lib/value.spec.ts @@ -48,4 +48,17 @@ describe('getValue', () => { window.history.replaceState({}, '', `${window.location.pathname}${originalSearch}`); }); + + it('should handle multiple QUERY patterns correctly with sanitization and validation', async () => { + const searchParams = new URLSearchParams(); + searchParams.set('param1', 'value1'); + searchParams.set('param2', 'value2'); + const originalSearch = window.location.search; + window.history.replaceState({}, '', `${window.location.pathname}?${searchParams.toString()}`); + + const result = await Value.getValue(' and '); + expect(result).toBe('value1 and value2<script>alert(1)</script>'); + + window.history.replaceState({}, '', `${window.location.pathname}${originalSearch}`); + }); }); diff --git a/libs/acf/util/src/lib/value.ts b/libs/acf/util/src/lib/value.ts index 2a8aac3e..352c3cdc 100644 --- a/libs/acf/util/src/lib/value.ts +++ b/libs/acf/util/src/lib/value.ts @@ -39,11 +39,25 @@ export const Value = (() => { const getSessionCount = (value: string) => value.replaceAll('', String(window.__sessionCount)); + const sanitizeInput = (input: string): string => { + const element = document.createElement('div'); + element.innerText = input; + return element.innerHTML; + }; + + const validateQueryParam = (key: string, value: string): boolean => { + const pattern = /^[a-zA-Z0-9_-]+$/; + return pattern.test(key) && pattern.test(value); + }; + const getQueryParam = (value: string) => { const [, key] = value.split('::'); const searchParams = new URLSearchParams(window.location.search); if (searchParams.has(key)) { - value = searchParams.get(key) || key; + const paramValue = searchParams.get(key) || key; + if (validateQueryParam(key, paramValue)) { + value = sanitizeInput(paramValue); + } } return value; }; @@ -51,7 +65,11 @@ export const Value = (() => { const getMultiQueryParam = (value: string) => { value = value.replace(VALUE_MATCHER.QUERY, (_, key) => { const searchParams = new URLSearchParams(window.location.search); - return searchParams.get(key) || key; + const paramValue = searchParams.get(key) || key; + if (validateQueryParam(key, paramValue)) { + return sanitizeInput(paramValue); + } + return key; }); return value; };