From 28e012b2edb8766295589e254faa9017221ec7f7 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Wed, 2 Oct 2024 22:07:41 +1000 Subject: [PATCH] [8.x] [ML] Various fixes for possible prototype pollution vulnerabilities (#194529) (#194660) # Backport This will backport the following commits from `main` to `8.x`: - [[ML] Various fixes for possible prototype pollution vulnerabilities (#194529)](https://github.com/elastic/kibana/pull/194529) ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) Co-authored-by: James Gowdy --- .../ml/nested_property/src/set_nested_property.test.ts | 10 ++++++++++ .../ml/nested_property/src/set_nested_property.ts | 6 ++++++ x-pack/plugins/ml/server/saved_objects/service.ts | 4 ++-- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/x-pack/packages/ml/nested_property/src/set_nested_property.test.ts b/x-pack/packages/ml/nested_property/src/set_nested_property.test.ts index 43996f603ffa0..963b0611197db 100644 --- a/x-pack/packages/ml/nested_property/src/set_nested_property.test.ts +++ b/x-pack/packages/ml/nested_property/src/set_nested_property.test.ts @@ -68,5 +68,15 @@ describe('object_utils', () => { const test11 = setNestedProperty(getFalseyObject(), 'the.other_nested.value', 'update'); expect(test11.the.other_nested.value).toBe('update'); + + expect(() => { + setNestedProperty(getTestObj(), 'the.__proto__', 'update'); + }).toThrow('Invalid accessor'); + expect(() => { + setNestedProperty(getTestObj(), 'the.prototype', 'update'); + }).toThrow('Invalid accessor'); + expect(() => { + setNestedProperty(getTestObj(), 'the.constructor', 'update'); + }).toThrow('Invalid accessor'); }); }); 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 b963983cb16ab..6c692cb3a0a08 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 @@ -5,9 +5,15 @@ * 2.0. */ +const INVALID_ACCESSORS = ['__proto__', 'prototype', 'constructor']; + export const setNestedProperty = (obj: Record, accessor: string, value: any) => { let ref = obj; const accessors = accessor.split('.'); + if (accessors.some((a) => INVALID_ACCESSORS.includes(a))) { + throw new Error('Invalid accessor'); + } + const len = accessors.length; for (let i = 0; i < len - 1; i++) { const attribute = accessors[i]; diff --git a/x-pack/plugins/ml/server/saved_objects/service.ts b/x-pack/plugins/ml/server/saved_objects/service.ts index e6c32f2bc6531..3e0f81a8ba13b 100644 --- a/x-pack/plugins/ml/server/saved_objects/service.ts +++ b/x-pack/plugins/ml/server/saved_objects/service.ts @@ -328,7 +328,7 @@ export function mlSavedObjectServiceFactory( if (id.match('\\*') === null) { return jobIds.includes(id); } - const regex = new RegExp(id.replace('*', '.*')); + const regex = new RegExp(id.replaceAll('*', '.*')); return jobIds.some((jId) => typeof jId === 'string' && regex.exec(jId)); }); } @@ -640,7 +640,7 @@ export function mlSavedObjectServiceFactory( if (id.match('\\*') === null) { return modelIds.includes(id); } - const regex = new RegExp(id.replace('*', '.*')); + const regex = new RegExp(id.replaceAll('*', '.*')); return modelIds.some((jId) => typeof jId === 'string' && regex.exec(jId)); }); }