From e204184a2ad12db23cc8a41dc260f8d282b4a8ae Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Tue, 3 Sep 2024 10:08:21 +0100 Subject: [PATCH] [ML] Improving empty object creation in ML packages (#191901) Replacing instances of empty object creation with Object.create(null) to remove any risk of prototype pollution. Related to https://github.com/elastic/kibana/pull/191518 --- .../queries/get_field_value_pair_counts.ts | 2 +- .../ml/is_populated_object/src/is_populated_object.test.ts | 4 ++++ .../ml/is_populated_object/src/is_populated_object.ts | 3 +-- x-pack/packages/ml/json_schemas/src/json_schema_service.ts | 2 +- x-pack/packages/ml/nested_property/src/set_nested_property.ts | 2 +- .../ml/random_sampler_utils/src/random_sampler_manager.ts | 2 +- .../runtime_field_utils/src/get_combined_runtime_mappings.ts | 2 +- x-pack/packages/ml/url_state/src/url_state.tsx | 4 ++-- 8 files changed, 12 insertions(+), 9 deletions(-) diff --git a/x-pack/packages/ml/aiops_log_rate_analysis/queries/get_field_value_pair_counts.ts b/x-pack/packages/ml/aiops_log_rate_analysis/queries/get_field_value_pair_counts.ts index e6f58f7c58e7b..779aaf1dfa9d3 100644 --- a/x-pack/packages/ml/aiops_log_rate_analysis/queries/get_field_value_pair_counts.ts +++ b/x-pack/packages/ml/aiops_log_rate_analysis/queries/get_field_value_pair_counts.ts @@ -16,7 +16,7 @@ export function getFieldValuePairCounts(cpgs: SignificantItemGroup[]): FieldValu return cpgs.reduce((p, { group }) => { group.forEach(({ fieldName, fieldValue }) => { if (p[fieldName] === undefined) { - p[fieldName] = {}; + p[fieldName] = Object.create(null); } p[fieldName][fieldValue] = p[fieldName][fieldValue] ? p[fieldName][fieldValue] + 1 : 1; }); diff --git a/x-pack/packages/ml/is_populated_object/src/is_populated_object.test.ts b/x-pack/packages/ml/is_populated_object/src/is_populated_object.test.ts index c606c0677cf67..fdbe8d9fa5f21 100644 --- a/x-pack/packages/ml/is_populated_object/src/is_populated_object.test.ts +++ b/x-pack/packages/ml/is_populated_object/src/is_populated_object.test.ts @@ -45,4 +45,8 @@ describe('isPopulatedObject', () => { ]) ).toBe(false); }); + it('does not allow an object with a required attribute in the prototype ', () => { + const testObject = { attribute: 'value', __proto__: { otherAttribute: 'value' } }; + expect(isPopulatedObject(testObject, ['otherAttribute'])).toBe(false); + }); }); diff --git a/x-pack/packages/ml/is_populated_object/src/is_populated_object.ts b/x-pack/packages/ml/is_populated_object/src/is_populated_object.ts index e8233b38cf356..7fee714dbd6a0 100644 --- a/x-pack/packages/ml/is_populated_object/src/is_populated_object.ts +++ b/x-pack/packages/ml/is_populated_object/src/is_populated_object.ts @@ -30,7 +30,6 @@ export const isPopulatedObject = 0 && - (requiredAttributes.length === 0 || - requiredAttributes.every((d) => ({}.hasOwnProperty.call(arg, d)))) + (requiredAttributes.length === 0 || requiredAttributes.every((d) => Object.hasOwn(arg, d))) ); }; diff --git a/x-pack/packages/ml/json_schemas/src/json_schema_service.ts b/x-pack/packages/ml/json_schemas/src/json_schema_service.ts index 44cd99edab622..876a65f9430a2 100644 --- a/x-pack/packages/ml/json_schemas/src/json_schema_service.ts +++ b/x-pack/packages/ml/json_schemas/src/json_schema_service.ts @@ -68,7 +68,7 @@ export class JsonSchemaService { }; } - private allComponents: Record = {}; + private allComponents: Record = Object.create(null); private componentsDict = new Set(); /** diff --git a/x-pack/packages/ml/nested_property/src/set_nested_property.ts b/x-pack/packages/ml/nested_property/src/set_nested_property.ts index 01e2200d4369a..b963983cb16ab 100644 --- a/x-pack/packages/ml/nested_property/src/set_nested_property.ts +++ b/x-pack/packages/ml/nested_property/src/set_nested_property.ts @@ -12,7 +12,7 @@ export const setNestedProperty = (obj: Record, accessor: string, va for (let i = 0; i < len - 1; i++) { const attribute = accessors[i]; if (typeof ref[attribute] !== 'object') { - ref[attribute] = {}; + ref[attribute] = Object.create(null); } ref = ref[attribute]; diff --git a/x-pack/packages/ml/random_sampler_utils/src/random_sampler_manager.ts b/x-pack/packages/ml/random_sampler_utils/src/random_sampler_manager.ts index 90568dd4ba5fb..56a2a9367e565 100644 --- a/x-pack/packages/ml/random_sampler_utils/src/random_sampler_manager.ts +++ b/x-pack/packages/ml/random_sampler_utils/src/random_sampler_manager.ts @@ -158,7 +158,7 @@ export class RandomSampler { const mode = this.getMode(); const probability = this.getProbability(); - let prob = {}; + let prob = Object.create(null); if (mode === RANDOM_SAMPLER_OPTION.ON_MANUAL) { prob = { probability }; } else if (mode === RANDOM_SAMPLER_OPTION.OFF) { diff --git a/x-pack/packages/ml/runtime_field_utils/src/get_combined_runtime_mappings.ts b/x-pack/packages/ml/runtime_field_utils/src/get_combined_runtime_mappings.ts index eebc7e7b13051..c348eb82cf0ac 100644 --- a/x-pack/packages/ml/runtime_field_utils/src/get_combined_runtime_mappings.ts +++ b/x-pack/packages/ml/runtime_field_utils/src/get_combined_runtime_mappings.ts @@ -18,7 +18,7 @@ export function getCombinedRuntimeMappings( dataView: DataView | undefined, runtimeMappings?: RuntimeMappings ): RuntimeMappings | undefined { - let combinedRuntimeMappings = {}; + let combinedRuntimeMappings = Object.create(null); // Add runtime field mappings defined by index pattern if (dataView) { diff --git a/x-pack/packages/ml/url_state/src/url_state.tsx b/x-pack/packages/ml/url_state/src/url_state.tsx index 4fd5dfe6e0538..7cd6bc1d812e6 100644 --- a/x-pack/packages/ml/url_state/src/url_state.tsx +++ b/x-pack/packages/ml/url_state/src/url_state.tsx @@ -67,7 +67,7 @@ export function isRisonSerializationRequired(queryParam: string): boolean { } export function parseUrlState(search: string): Dictionary { - const urlState: Dictionary = {}; + const urlState: Dictionary = Object.create(null); const parsedQueryString = parse(search, { sort: false }); try { @@ -125,7 +125,7 @@ export const UrlStateProvider: FC> = ({ children }) = const parsedQueryString = parse(prevSearchString, { sort: false }); if (!Object.hasOwn(urlState, accessor)) { - urlState[accessor] = {}; + urlState[accessor] = Object.create(null); } if (typeof attribute === 'string') {