From 579d30fe52c0f7d6ff08795fb2bc95f544b0313c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Fri, 4 Aug 2023 13:49:43 +0200 Subject: [PATCH] fix(search-bar): add validation for value token in WQL --- .../search-bar/query-language/wql.test.tsx | 93 ++++++++++--------- .../search-bar/query-language/wql.tsx | 28 ++++-- 2 files changed, 70 insertions(+), 51 deletions(-) diff --git a/plugins/main/public/components/search-bar/query-language/wql.test.tsx b/plugins/main/public/components/search-bar/query-language/wql.test.tsx index 5cdecb968b..4de5de790b 100644 --- a/plugins/main/public/components/search-bar/query-language/wql.test.tsx +++ b/plugins/main/public/components/search-bar/query-language/wql.test.tsx @@ -397,48 +397,52 @@ describe('Query language - WQL', () => { */ // Validate the tokens + // Some examples of value tokens are based on this API test: https://github.com/wazuh/wazuh/blob/813595cf58d753c1066c3e7c2018dbb4708df088/framework/wazuh/core/tests/test_utils.py#L987-L1050 it.each` - WQL | validationError - ${''} | ${undefined} - ${'field1'} | ${undefined} - ${'field2'} | ${undefined} - ${'field1='} | ${['The value for field "field1" is missing.']} - ${'field2='} | ${['The value for field "field2" is missing.']} - ${'field='} | ${['"field" is not a valid field.']} - ${'custom='} | ${['"custom" is not a valid field.']} - ${'field1=value'} | ${undefined} - ${'field1=1'} | ${['Numbers are not valid for field1']} - ${'field1=value1'} | ${['Numbers are not valid for field1']} - ${'field2=value'} | ${undefined} - ${'field=value'} | ${['"field" is not a valid field.']} - ${'custom=value'} | ${['"custom" is not a valid field.']} - ${'field1=value!test'} | ${['"value!test" is not a valid value. Invalid characters found: !']} - ${'field1=value&test'} | ${['"value&test" is not a valid value. Invalid characters found: &']} - ${'field1=value!value&test'} | ${['"value!value&test" is not a valid value. Invalid characters found: !&']} - ${'field1=value!value!test'} | ${['"value!value!test" is not a valid value. Invalid characters found: !']} - ${'field1=value!value!t$&st'} | ${['"value!value!t$&st" is not a valid value. Invalid characters found: !$&']} - ${'field1=value and'} | ${['There is no whitespace after conjunction "and".', 'There is no sentence after conjunction "and".']} - ${'field2=value and'} | ${['There is no whitespace after conjunction "and".', 'There is no sentence after conjunction "and".']} - ${'field=value and'} | ${['"field" is not a valid field.', 'There is no whitespace after conjunction "and".', 'There is no sentence after conjunction "and".']} - ${'custom=value and'} | ${['"custom" is not a valid field.', 'There is no whitespace after conjunction "and".', 'There is no sentence after conjunction "and".']} - ${'field1=value and '} | ${['There is no sentence after conjunction "and".']} - ${'field2=value and '} | ${['There is no sentence after conjunction "and".']} - ${'field=value and '} | ${['"field" is not a valid field.', 'There is no sentence after conjunction "and".']} - ${'custom=value and '} | ${['"custom" is not a valid field.', 'There is no sentence after conjunction "and".']} - ${'field1=value and field2'} | ${['The operator for field "field2" is missing.']} - ${'field2=value and field1'} | ${['The operator for field "field1" is missing.']} - ${'field1=value and field'} | ${['"field" is not a valid field.']} - ${'field2=value and field'} | ${['"field" is not a valid field.']} - ${'field=value and custom'} | ${['"field" is not a valid field.', '"custom" is not a valid field.']} - ${'('} | ${undefined} - ${'(field'} | ${undefined} - ${'(field='} | ${['"field" is not a valid field.']} - ${'(field=value'} | ${['"field" is not a valid field.']} - ${'(field=value or'} | ${['"field" is not a valid field.', 'There is no whitespace after conjunction "or".', 'There is no sentence after conjunction "or".']} - ${'(field=value or '} | ${['"field" is not a valid field.', 'There is no sentence after conjunction "or".']} - ${'(field=value or field2'} | ${['"field" is not a valid field.', 'The operator for field "field2" is missing.']} - ${'(field=value or field2>'} | ${['"field" is not a valid field.', 'The value for field "field2" is missing.']} - ${'(field=value or field2>value2'} | ${['"field" is not a valid field.']} + WQL | validationError + ${''} | ${undefined} + ${'field1'} | ${undefined} + ${'field2'} | ${undefined} + ${'field1='} | ${['The value for field "field1" is missing.']} + ${'field2='} | ${['The value for field "field2" is missing.']} + ${'field='} | ${['"field" is not a valid field.']} + ${'custom='} | ${['"custom" is not a valid field.']} + ${'field1=value'} | ${undefined} + ${'field_not_number=1'} | ${['Numbers are not valid for field_not_number']} + ${'field_not_number=value1'} | ${['Numbers are not valid for field_not_number']} + ${'field2=value'} | ${undefined} + ${'field=value'} | ${['"field" is not a valid field.']} + ${'custom=value'} | ${['"custom" is not a valid field.']} + ${'field1=value!test'} | ${['"value!test" is not a valid value. Invalid characters found: !']} + ${'field1=value&test'} | ${['"value&test" is not a valid value. Invalid characters found: &']} + ${'field1=value!value&test'} | ${['"value!value&test" is not a valid value. Invalid characters found: !&']} + ${'field1=value!value!test'} | ${['"value!value!test" is not a valid value. Invalid characters found: !']} + ${'field1=value!value!t$&st'} | ${['"value!value!t$&st" is not a valid value. Invalid characters found: !$&']} + ${'field1=value,'} | ${['"value," is not a valid value.']} + ${'field1="Mozilla Firefox 53.0 (x64 en-US)"'} | ${undefined} + ${'field1="[\\"https://example-link@<>=,%?\\"]"'} | ${undefined} + ${'field1=value and'} | ${['There is no whitespace after conjunction "and".', 'There is no sentence after conjunction "and".']} + ${'field2=value and'} | ${['There is no whitespace after conjunction "and".', 'There is no sentence after conjunction "and".']} + ${'field=value and'} | ${['"field" is not a valid field.', 'There is no whitespace after conjunction "and".', 'There is no sentence after conjunction "and".']} + ${'custom=value and'} | ${['"custom" is not a valid field.', 'There is no whitespace after conjunction "and".', 'There is no sentence after conjunction "and".']} + ${'field1=value and '} | ${['There is no sentence after conjunction "and".']} + ${'field2=value and '} | ${['There is no sentence after conjunction "and".']} + ${'field=value and '} | ${['"field" is not a valid field.', 'There is no sentence after conjunction "and".']} + ${'custom=value and '} | ${['"custom" is not a valid field.', 'There is no sentence after conjunction "and".']} + ${'field1=value and field2'} | ${['The operator for field "field2" is missing.']} + ${'field2=value and field1'} | ${['The operator for field "field1" is missing.']} + ${'field1=value and field'} | ${['"field" is not a valid field.']} + ${'field2=value and field'} | ${['"field" is not a valid field.']} + ${'field=value and custom'} | ${['"field" is not a valid field.', '"custom" is not a valid field.']} + ${'('} | ${undefined} + ${'(field'} | ${undefined} + ${'(field='} | ${['"field" is not a valid field.']} + ${'(field=value'} | ${['"field" is not a valid field.']} + ${'(field=value or'} | ${['"field" is not a valid field.', 'There is no whitespace after conjunction "or".', 'There is no sentence after conjunction "or".']} + ${'(field=value or '} | ${['"field" is not a valid field.', 'There is no sentence after conjunction "or".']} + ${'(field=value or field2'} | ${['"field" is not a valid field.', 'The operator for field "field2" is missing.']} + ${'(field=value or field2>'} | ${['"field" is not a valid field.', 'The value for field "field2" is missing.']} + ${'(field=value or field2>value2'} | ${['"field" is not a valid field.']} `( 'validate the tokens - WQL $WQL => $validationError', async ({ WQL: currentInput, validationError }) => { @@ -447,12 +451,15 @@ describe('Query language - WQL', () => { parameters: { options: {}, suggestions: { - field: () => ['field1', 'field2'].map(label => ({ label })), + field: () => + ['field1', 'field2', 'field_not_number'].map(label => ({ + label, + })), value: () => [], }, validate: { value: (token, { field, operator_compare }) => { - if (field === 'field1') { + if (field === 'field_not_number') { const value = token.formattedValue || token.value; return /\d/.test(value) ? `Numbers are not valid for ${field}` diff --git a/plugins/main/public/components/search-bar/query-language/wql.tsx b/plugins/main/public/components/search-bar/query-language/wql.tsx index 7470587f45..06bddbc1c5 100644 --- a/plugins/main/public/components/search-bar/query-language/wql.tsx +++ b/plugins/main/public/components/search-bar/query-language/wql.tsx @@ -685,6 +685,20 @@ function getOutput(input: string, options: OptionsQL) { * @returns */ function validateTokenValue(token: IToken): string | undefined { + const re = new RegExp( + // Value: A string. + '^(?(?:(?:\\((?:\\[[\\[\\]\\w _\\-.,:?\\\\/\'"=@%<>{}]*]|[\\[\\]\\w _\\-.:?\\/\'"=@%<>{}]*)\\))*' + + '(?:\\[[\\[\\]\\w _\\-.,:?\\\\/\'"=@%<>{}]*]|^[\\[\\]\\w _\\-.:?\\\\/\'"=@%<>{}]+)' + + '(?:\\((?:\\[[\\[\\]\\w _\\-.,:?\\\\/\'"=@%<>{}]*]|[\\[\\]\\w _\\-.:?\\\\/\'"=@%<>{}]*)\\))*)+)$', + ); + + const value = token.formattedValue ?? token.value; + const match = value.match(re); + + if (match?.groups?.value === value) { + return undefined; + } + const invalidCharacters: string[] = token.value .split('') .filter((value, index, array) => array.indexOf(value) === index) @@ -695,14 +709,12 @@ function validateTokenValue(token: IToken): string | undefined { ), ); - return !invalidCharacters.length - ? undefined - : [ - `"${token.value}" is not a valid value.`, - ...(invalidCharacters.length - ? [`Invalid characters found: ${invalidCharacters.join('')}`] - : []), - ].join(' '); + return [ + `"${token.value}" is not a valid value.`, + ...(invalidCharacters.length + ? [`Invalid characters found: ${invalidCharacters.join('')}`] + : []), + ].join(' '); } type ITokenValidator = (