diff --git a/.ci/packer_cache_for_branch.sh b/.ci/packer_cache_for_branch.sh
index 5b4a94be50fa2..ab0ab845b2dc3 100755
--- a/.ci/packer_cache_for_branch.sh
+++ b/.ci/packer_cache_for_branch.sh
@@ -18,7 +18,7 @@ node scripts/es snapshot --download-only;
node scripts/es snapshot --license=oss --download-only;
# download reporting browsers
-(cd "x-pack" && yarn gulp prepare);
+(cd "x-pack" && yarn gulp downloadChromium);
# cache the chromedriver archive
chromedriverDistVersion="$(node -e "console.log(require('chromedriver').version)")"
diff --git a/.eslintrc.js b/.eslintrc.js
index 4425ad3a12659..a9ffe2850aa72 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -49,6 +49,31 @@ const ELASTIC_LICENSE_HEADER = `
*/
`;
+const SAFER_LODASH_SET_HEADER = `
+/*
+ * Elasticsearch B.V licenses this file to you under the MIT License.
+ * See \`packages/elastic-safer-lodash-set/LICENSE\` for more information.
+ */
+`;
+
+const SAFER_LODASH_SET_LODASH_HEADER = `
+/*
+ * This file is forked from the lodash project (https://lodash.com/),
+ * and may include modifications made by Elasticsearch B.V.
+ * Elasticsearch B.V. licenses this file to you under the MIT License.
+ * See \`packages/elastic-safer-lodash-set/LICENSE\` for more information.
+ */
+`;
+
+const SAFER_LODASH_SET_DEFINITELYTYPED_HEADER = `
+/*
+ * This file is forked from the DefinitelyTyped project (https://github.com/DefinitelyTyped/DefinitelyTyped),
+ * and may include modifications made by Elasticsearch B.V.
+ * Elasticsearch B.V. licenses this file to you under the MIT License.
+ * See \`packages/elastic-safer-lodash-set/LICENSE\` for more information.
+ */
+`;
+
const allMochaRulesOff = {};
Object.keys(require('eslint-plugin-mocha').rules).forEach((k) => {
allMochaRulesOff['mocha/' + k] = 'off';
@@ -143,7 +168,12 @@ module.exports = {
'@kbn/eslint/disallow-license-headers': [
'error',
{
- licenses: [ELASTIC_LICENSE_HEADER],
+ licenses: [
+ ELASTIC_LICENSE_HEADER,
+ SAFER_LODASH_SET_HEADER,
+ SAFER_LODASH_SET_LODASH_HEADER,
+ SAFER_LODASH_SET_DEFINITELYTYPED_HEADER,
+ ],
},
],
},
@@ -174,7 +204,82 @@ module.exports = {
'@kbn/eslint/disallow-license-headers': [
'error',
{
- licenses: [APACHE_2_0_LICENSE_HEADER],
+ licenses: [
+ APACHE_2_0_LICENSE_HEADER,
+ SAFER_LODASH_SET_HEADER,
+ SAFER_LODASH_SET_LODASH_HEADER,
+ SAFER_LODASH_SET_DEFINITELYTYPED_HEADER,
+ ],
+ },
+ ],
+ },
+ },
+
+ /**
+ * safer-lodash-set package requires special license headers
+ */
+ {
+ files: ['packages/elastic-safer-lodash-set/**/*.{js,mjs,ts,tsx}'],
+ rules: {
+ '@kbn/eslint/require-license-header': [
+ 'error',
+ {
+ license: SAFER_LODASH_SET_LODASH_HEADER,
+ },
+ ],
+ '@kbn/eslint/disallow-license-headers': [
+ 'error',
+ {
+ licenses: [
+ ELASTIC_LICENSE_HEADER,
+ APACHE_2_0_LICENSE_HEADER,
+ SAFER_LODASH_SET_HEADER,
+ SAFER_LODASH_SET_DEFINITELYTYPED_HEADER,
+ ],
+ },
+ ],
+ },
+ },
+ {
+ files: ['packages/elastic-safer-lodash-set/test/*.{js,mjs,ts,tsx}'],
+ rules: {
+ '@kbn/eslint/require-license-header': [
+ 'error',
+ {
+ license: SAFER_LODASH_SET_HEADER,
+ },
+ ],
+ '@kbn/eslint/disallow-license-headers': [
+ 'error',
+ {
+ licenses: [
+ ELASTIC_LICENSE_HEADER,
+ APACHE_2_0_LICENSE_HEADER,
+ SAFER_LODASH_SET_LODASH_HEADER,
+ SAFER_LODASH_SET_DEFINITELYTYPED_HEADER,
+ ],
+ },
+ ],
+ },
+ },
+ {
+ files: ['packages/elastic-safer-lodash-set/**/*.d.ts'],
+ rules: {
+ '@kbn/eslint/require-license-header': [
+ 'error',
+ {
+ license: SAFER_LODASH_SET_DEFINITELYTYPED_HEADER,
+ },
+ ],
+ '@kbn/eslint/disallow-license-headers': [
+ 'error',
+ {
+ licenses: [
+ ELASTIC_LICENSE_HEADER,
+ APACHE_2_0_LICENSE_HEADER,
+ SAFER_LODASH_SET_HEADER,
+ SAFER_LODASH_SET_LODASH_HEADER,
+ ],
},
],
},
@@ -541,9 +646,129 @@ module.exports = {
* Harden specific rules
*/
{
- files: ['test/harden/*.js'],
+ files: ['test/harden/*.js', 'packages/elastic-safer-lodash-set/test/*.js'],
rules: allMochaRulesOff,
},
+ {
+ files: ['**/*.{js,mjs,ts,tsx}'],
+ rules: {
+ 'no-restricted-imports': [
+ 2,
+ {
+ paths: [
+ {
+ name: 'lodash',
+ importNames: ['set', 'setWith'],
+ message: 'Please use @elastic/safer-lodash-set instead',
+ },
+ {
+ name: 'lodash.set',
+ message: 'Please use @elastic/safer-lodash-set instead',
+ },
+ {
+ name: 'lodash.setwith',
+ message: 'Please use @elastic/safer-lodash-set instead',
+ },
+ {
+ name: 'lodash/set',
+ message: 'Please use @elastic/safer-lodash-set instead',
+ },
+ {
+ name: 'lodash/setWith',
+ message: 'Please use @elastic/safer-lodash-set instead',
+ },
+ {
+ name: 'lodash/fp',
+ importNames: ['set', 'setWith', 'assoc', 'assocPath'],
+ message: 'Please use @elastic/safer-lodash-set instead',
+ },
+ {
+ name: 'lodash/fp/set',
+ message: 'Please use @elastic/safer-lodash-set instead',
+ },
+ {
+ name: 'lodash/fp/setWith',
+ message: 'Please use @elastic/safer-lodash-set instead',
+ },
+ {
+ name: 'lodash/fp/assoc',
+ message: 'Please use @elastic/safer-lodash-set instead',
+ },
+ {
+ name: 'lodash/fp/assocPath',
+ message: 'Please use @elastic/safer-lodash-set instead',
+ },
+ ],
+ },
+ ],
+ 'no-restricted-modules': [
+ 2,
+ {
+ paths: [
+ {
+ name: 'lodash.set',
+ message: 'Please use @elastic/safer-lodash-set instead',
+ },
+ {
+ name: 'lodash.setwith',
+ message: 'Please use @elastic/safer-lodash-set instead',
+ },
+ {
+ name: 'lodash/set',
+ message: 'Please use @elastic/safer-lodash-set instead',
+ },
+ {
+ name: 'lodash/setWith',
+ message: 'Please use @elastic/safer-lodash-set instead',
+ },
+ ],
+ },
+ ],
+ 'no-restricted-properties': [
+ 2,
+ {
+ object: 'lodash',
+ property: 'set',
+ message: 'Please use @elastic/safer-lodash-set instead',
+ },
+ {
+ object: '_',
+ property: 'set',
+ message: 'Please use @elastic/safer-lodash-set instead',
+ },
+ {
+ object: 'lodash',
+ property: 'setWith',
+ message: 'Please use @elastic/safer-lodash-set instead',
+ },
+ {
+ object: '_',
+ property: 'setWith',
+ message: 'Please use @elastic/safer-lodash-set instead',
+ },
+ {
+ object: 'lodash',
+ property: 'assoc',
+ message: 'Please use @elastic/safer-lodash-set instead',
+ },
+ {
+ object: '_',
+ property: 'assoc',
+ message: 'Please use @elastic/safer-lodash-set instead',
+ },
+ {
+ object: 'lodash',
+ property: 'assocPath',
+ message: 'Please use @elastic/safer-lodash-set instead',
+ },
+ {
+ object: '_',
+ property: 'assocPath',
+ message: 'Please use @elastic/safer-lodash-set instead',
+ },
+ ],
+ },
+ },
/**
* APM overrides
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.embeddable.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.embeddable.md
new file mode 100644
index 0000000000000..027ae4209b77f
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.embeddable.md
@@ -0,0 +1,11 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [ApplyGlobalFilterActionContext](./kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.md) > [embeddable](./kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.embeddable.md)
+
+## ApplyGlobalFilterActionContext.embeddable property
+
+Signature:
+
+```typescript
+embeddable?: IEmbeddable;
+```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.filters.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.filters.md
new file mode 100644
index 0000000000000..6d1d20580fb19
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.filters.md
@@ -0,0 +1,11 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [ApplyGlobalFilterActionContext](./kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.md) > [filters](./kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.filters.md)
+
+## ApplyGlobalFilterActionContext.filters property
+
+Signature:
+
+```typescript
+filters: Filter[];
+```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.md
new file mode 100644
index 0000000000000..62817cd0a1e33
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.md
@@ -0,0 +1,20 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [ApplyGlobalFilterActionContext](./kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.md)
+
+## ApplyGlobalFilterActionContext interface
+
+Signature:
+
+```typescript
+export interface ApplyGlobalFilterActionContext
+```
+
+## Properties
+
+| Property | Type | Description |
+| --- | --- | --- |
+| [embeddable](./kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.embeddable.md) | IEmbeddable
| |
+| [filters](./kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.filters.md) | Filter[]
| |
+| [timeFieldName](./kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.timefieldname.md) | string
| |
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.timefieldname.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.timefieldname.md
new file mode 100644
index 0000000000000..a5cf58018ec65
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.timefieldname.md
@@ -0,0 +1,11 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [ApplyGlobalFilterActionContext](./kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.md) > [timeFieldName](./kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.timefieldname.md)
+
+## ApplyGlobalFilterActionContext.timeFieldName property
+
+Signature:
+
+```typescript
+timeFieldName?: string;
+```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md
index 4852ad15781c7..db41936f35cca 100644
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md
@@ -48,6 +48,7 @@
| Interface | Description |
| --- | --- |
| [AggParamOption](./kibana-plugin-plugins-data-public.aggparamoption.md) | |
+| [ApplyGlobalFilterActionContext](./kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.md) | |
| [DataPublicPluginSetup](./kibana-plugin-plugins-data-public.datapublicpluginsetup.md) | |
| [DataPublicPluginStart](./kibana-plugin-plugins-data-public.datapublicpluginstart.md) | |
| [EsQueryConfig](./kibana-plugin-plugins-data-public.esqueryconfig.md) | |
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.plugin.setup.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.plugin.setup.md
index 51bc46bbdccc8..a0c9b38792825 100644
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.plugin.setup.md
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.plugin.setup.md
@@ -7,15 +7,15 @@
Signature:
```typescript
-setup(core: CoreSetup, { expressions, uiActions }: DataSetupDependencies): DataPublicPluginSetup;
+setup(core: CoreSetup, { expressions, uiActions, usageCollection }: DataSetupDependencies): DataPublicPluginSetup;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
-| core | CoreSetup
| |
-| { expressions, uiActions } | DataSetupDependencies
| |
+| core | CoreSetup<DataStartDependencies, DataPublicPluginStart>
| |
+| { expressions, uiActions, usageCollection } | DataSetupDependencies
| |
Returns:
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.md
index abd57f3a9568b..1291af5359887 100644
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.md
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.md
@@ -18,4 +18,5 @@ export interface SearchInterceptorDeps
| [http](./kibana-plugin-plugins-data-public.searchinterceptordeps.http.md) | CoreStart['http']
| |
| [toasts](./kibana-plugin-plugins-data-public.searchinterceptordeps.toasts.md) | ToastsStart
| |
| [uiSettings](./kibana-plugin-plugins-data-public.searchinterceptordeps.uisettings.md) | CoreStart['uiSettings']
| |
+| [usageCollector](./kibana-plugin-plugins-data-public.searchinterceptordeps.usagecollector.md) | SearchUsageCollector
| |
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.usagecollector.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.usagecollector.md
new file mode 100644
index 0000000000000..21afce1927676
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.usagecollector.md
@@ -0,0 +1,11 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchInterceptorDeps](./kibana-plugin-plugins-data-public.searchinterceptordeps.md) > [usageCollector](./kibana-plugin-plugins-data-public.searchinterceptordeps.usagecollector.md)
+
+## SearchInterceptorDeps.usageCollector property
+
+Signature:
+
+```typescript
+usageCollector?: SearchUsageCollector;
+```
diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.isearchsetup.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.isearchsetup.md
index ca8ad8fdc06ea..3afba80064f08 100644
--- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.isearchsetup.md
+++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.isearchsetup.md
@@ -14,5 +14,6 @@ export interface ISearchSetup
| Property | Type | Description |
| --- | --- | --- |
-| [registerSearchStrategy](./kibana-plugin-plugins-data-server.isearchsetup.registersearchstrategy.md) | (name: string, strategy: ISearchStrategy) => void
| Extension point exposed for other plugins to register their own search strategies. |
+| [registerSearchStrategy](./kibana-plugin-plugins-data-server.isearchsetup.registersearchstrategy.md) | TRegisterSearchStrategy
| Extension point exposed for other plugins to register their own search strategies. |
+| [usage](./kibana-plugin-plugins-data-server.isearchsetup.usage.md) | SearchUsage
| Used internally for telemetry |
diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.isearchsetup.usage.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.isearchsetup.usage.md
new file mode 100644
index 0000000000000..85abd9d9dba98
--- /dev/null
+++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.isearchsetup.usage.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [ISearchSetup](./kibana-plugin-plugins-data-server.isearchsetup.md) > [usage](./kibana-plugin-plugins-data-server.isearchsetup.usage.md)
+
+## ISearchSetup.usage property
+
+Used internally for telemetry
+
+Signature:
+
+```typescript
+usage: SearchUsage;
+```
diff --git a/docs/settings/apm-settings.asciidoc b/docs/settings/apm-settings.asciidoc
index f78b0642f7fa3..b396c40aa21f9 100644
--- a/docs/settings/apm-settings.asciidoc
+++ b/docs/settings/apm-settings.asciidoc
@@ -47,7 +47,7 @@ Changing these settings may disable features of the APM App.
| Set to `false` to hide the APM app from the menu. Defaults to `true`.
| `xpack.apm.ui.transactionGroupBucketSize`
- | Number of top transaction groups displayed in the APM app. Defaults to `100`.
+ | Number of top transaction groups displayed in the APM app. Defaults to `1000`.
| `xpack.apm.ui.maxTraceItems` {ess-icon}
| Maximum number of child items displayed when viewing trace details. Defaults to `1000`.
diff --git a/examples/ui_actions_explorer/public/actions/actions.tsx b/examples/ui_actions_explorer/public/actions/actions.tsx
index 4ef8d5bf4d9c6..6d83362e998bc 100644
--- a/examples/ui_actions_explorer/public/actions/actions.tsx
+++ b/examples/ui_actions_explorer/public/actions/actions.tsx
@@ -31,7 +31,7 @@ export const ACTION_VIEW_IN_MAPS = 'ACTION_VIEW_IN_MAPS';
export const ACTION_TRAVEL_GUIDE = 'ACTION_TRAVEL_GUIDE';
export const ACTION_CALL_PHONE_NUMBER = 'ACTION_CALL_PHONE_NUMBER';
export const ACTION_EDIT_USER = 'ACTION_EDIT_USER';
-export const ACTION_PHONE_USER = 'ACTION_PHONE_USER';
+export const ACTION_TRIGGER_PHONE_USER = 'ACTION_TRIGGER_PHONE_USER';
export const ACTION_SHOWCASE_PLUGGABILITY = 'ACTION_SHOWCASE_PLUGGABILITY';
export const showcasePluggability = createAction({
@@ -120,19 +120,13 @@ export interface UserContext {
update: (user: User) => void;
}
-export const createPhoneUserAction = (getUiActionsApi: () => Promise) =>
- createAction({
- type: ACTION_PHONE_USER,
+export const createTriggerPhoneTriggerAction = (getUiActionsApi: () => Promise) =>
+ createAction({
+ type: ACTION_TRIGGER_PHONE_USER,
getDisplayName: () => 'Call phone number',
+ shouldAutoExecute: async () => true,
isCompatible: async ({ user }) => user.phone !== undefined,
execute: async ({ user }) => {
- // One option - execute the more specific action directly.
- // makePhoneCallAction.execute({ phone: user.phone });
-
- // Another option - emit the trigger and automatically get *all* the actions attached
- // to the phone number trigger.
- // TODO: we need to figure out the best way to handle these nested actions however, since
- // we don't want multiple context menu's to pop up.
if (user.phone !== undefined) {
(await getUiActionsApi()).executeTriggerActions(PHONE_TRIGGER, { phone: user.phone });
}
diff --git a/examples/ui_actions_explorer/public/plugin.tsx b/examples/ui_actions_explorer/public/plugin.tsx
index 670138b43b9c4..b28e5e7a9f692 100644
--- a/examples/ui_actions_explorer/public/plugin.tsx
+++ b/examples/ui_actions_explorer/public/plugin.tsx
@@ -23,7 +23,6 @@ import {
PHONE_TRIGGER,
USER_TRIGGER,
COUNTRY_TRIGGER,
- createPhoneUserAction,
lookUpWeatherAction,
viewInMapsAction,
createEditUserAction,
@@ -37,7 +36,8 @@ import {
ACTION_CALL_PHONE_NUMBER,
ACTION_TRAVEL_GUIDE,
ACTION_VIEW_IN_MAPS,
- ACTION_PHONE_USER,
+ ACTION_TRIGGER_PHONE_USER,
+ createTriggerPhoneTriggerAction,
} from './actions/actions';
import { DeveloperExamplesSetup } from '../../developer_examples/public';
import image from './ui_actions.png';
@@ -64,7 +64,7 @@ declare module '../../../src/plugins/ui_actions/public' {
[ACTION_CALL_PHONE_NUMBER]: PhoneContext;
[ACTION_TRAVEL_GUIDE]: CountryContext;
[ACTION_VIEW_IN_MAPS]: CountryContext;
- [ACTION_PHONE_USER]: UserContext;
+ [ACTION_TRIGGER_PHONE_USER]: UserContext;
}
}
@@ -84,7 +84,7 @@ export class UiActionsExplorerPlugin implements Plugin (await startServices)[1].uiActions)
+ createTriggerPhoneTriggerAction(async () => (await startServices)[1].uiActions)
);
deps.uiActions.addTriggerAction(
USER_TRIGGER,
diff --git a/package.json b/package.json
index 55a099b4e5c0c..53aa6b25f190b 100644
--- a/package.json
+++ b/package.json
@@ -132,6 +132,7 @@
"@elastic/good": "8.1.1-kibana2",
"@elastic/numeral": "^2.5.0",
"@elastic/request-crypto": "1.1.4",
+ "@elastic/safer-lodash-set": "0.0.0",
"@elastic/ui-ace": "0.2.3",
"@hapi/good-squeeze": "5.2.1",
"@hapi/wreck": "^15.0.2",
@@ -140,9 +141,9 @@
"@kbn/babel-preset": "1.0.0",
"@kbn/config-schema": "1.0.0",
"@kbn/i18n": "1.0.0",
- "@kbn/telemetry-tools": "1.0.0",
"@kbn/interpreter": "1.0.0",
"@kbn/pm": "1.0.0",
+ "@kbn/telemetry-tools": "1.0.0",
"@kbn/test-subj-selector": "0.2.1",
"@kbn/ui-framework": "1.0.0",
"@kbn/ui-shared-deps": "1.0.0",
@@ -344,6 +345,7 @@
"@types/hapi-auth-cookie": "^9.1.0",
"@types/has-ansi": "^3.0.0",
"@types/history": "^4.7.3",
+ "@types/hjson": "^2.4.2",
"@types/hoek": "^4.1.3",
"@types/inert": "^5.1.2",
"@types/jest": "^25.2.3",
diff --git a/packages/elastic-safer-lodash-set/.gitignore b/packages/elastic-safer-lodash-set/.gitignore
new file mode 100644
index 0000000000000..b152df746bf26
--- /dev/null
+++ b/packages/elastic-safer-lodash-set/.gitignore
@@ -0,0 +1,2 @@
+.tmp
+node_modules
diff --git a/packages/elastic-safer-lodash-set/.npmignore b/packages/elastic-safer-lodash-set/.npmignore
new file mode 100644
index 0000000000000..c2c910c637c01
--- /dev/null
+++ b/packages/elastic-safer-lodash-set/.npmignore
@@ -0,0 +1,3 @@
+tsconfig.json
+scripts
+test
diff --git a/packages/elastic-safer-lodash-set/LICENSE b/packages/elastic-safer-lodash-set/LICENSE
new file mode 100644
index 0000000000000..049225c0b6647
--- /dev/null
+++ b/packages/elastic-safer-lodash-set/LICENSE
@@ -0,0 +1,34 @@
+The MIT License (MIT)
+
+Copyright (c) Elasticsearch BV
+Copyright (c) Brian Zengel , Ilya Mochalov
+Copyright (c) JS Foundation and other contributors
+
+Lodash is based on Underscore.js, copyright Jeremy Ashkenas,
+DocumentCloud and Investigative Reporters & Editors
+
+This software consists of voluntary contributions made by many
+individuals. For exact contribution history, see the revision history
+available at the following locations:
+ - https://github.com/lodash/lodash
+ - https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/lodash
+ - https://github.com/elastic/kibana/tree/master/packages/elastic-safer-lodash-set
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/packages/elastic-safer-lodash-set/README.md b/packages/elastic-safer-lodash-set/README.md
new file mode 100644
index 0000000000000..aae17b35ac130
--- /dev/null
+++ b/packages/elastic-safer-lodash-set/README.md
@@ -0,0 +1,113 @@
+# @elastic/safer-lodash-set
+
+This module adds protection against prototype pollution to the [`set`]
+and [`setWith`] functions from [Lodash] and are API compatible with
+Lodash v4.x.
+
+## Example Usage
+
+```js
+const { set } = require('@elastic/safer-loadsh-set');
+
+const object = { a: [{ b: { c: 3 } }] };
+
+set(object, 'a[0].b.c', 4);
+console.log(object.a[0].b.c); // => 4
+
+set(object, ['x', '0', 'y', 'z'], 5);
+console.log(object.x[0].y.z); // => 5
+```
+
+## API
+
+The main module exposes two functions, `set` and `setWith`:
+
+```js
+const { set, setWith } = require('@elastic/safer-lodash-set');
+```
+
+Besides the main module, it's also possible to require each function
+individually:
+
+```js
+const set = require('@elastic/safer-lodash-set/set');
+const setWith = require('@elastic/safer-lodash-set/setWith');
+```
+
+The APIs of these functions are identical to the equivalent Lodash
+[`set`] and [`setWith`] functions. Please refer to the Lodash
+documentation for the respective functions for details.
+
+### Functional Programming support (fp)
+
+This module also supports the `lodash/fp` api and hence exposes the
+following fp compatible functions:
+
+```js
+const { set, setWith } = require('@elastic/safer-lodash-set/fp');
+```
+
+Besides the main fp module, it's also possible to require each function
+individually:
+
+```js
+const set = require('@elastic/safer-lodash-set/fp/set');
+const setWith = require('@elastic/safer-lodash-set/fp/setWith');
+```
+
+## Limitations
+
+The safety improvements in this module is achieved by adding the
+following limitations to the algorithm used to walk the `path` given as
+the 2nd argument to the `set` and `setWith` functions:
+
+### Only own properties are followed when walking the `path`
+
+```js
+const parent = { foo: 1 };
+const child = { bar: 2 };
+
+Object.setPrototypeOf(child, parent);
+
+// Now `child` can access `foo` through prototype inheritance
+console.log(child.foo); // 1
+
+set(child, 'foo', 3);
+
+// A different `foo` property has now been added directly to the `child`
+// object and the `parent` object has not been modified:
+console.log(child.foo); // 3
+console.log(parent.foo); // 1
+console.log(Object.prototype.hasOwnProperty.call(child, 'foo')); // true
+```
+
+### The `path` must not access function prototypes
+
+```js
+const object = {
+ fn1: function () {},
+ fn2: () => {},
+};
+
+// Attempting to access any function prototype will result in an
+// exception being thrown:
+assert.throws(() => {
+ // Throws: Illegal access of function prototype
+ set(object, 'fn1.prototype.toString', 'bang!');
+});
+
+// This also goes for arrow functions even though they don't have a
+// prototype property. This is just to keep things consistent:
+assert.throws(() => {
+ // Throws: Illegal access of function prototype
+ set(object, 'fn2.prototype.toString', 'bang!');
+});
+```
+
+## License
+
+[MIT](LICENSE)
+
+[`set`]: https://lodash.com/docs/4.17.15#set
+[`setwith`]: https://lodash.com/docs/4.17.15#setWith
+[lodash]: https://lodash.com/
diff --git a/packages/elastic-safer-lodash-set/fp/assoc.d.ts b/packages/elastic-safer-lodash-set/fp/assoc.d.ts
new file mode 100644
index 0000000000000..57fe84d0b07f2
--- /dev/null
+++ b/packages/elastic-safer-lodash-set/fp/assoc.d.ts
@@ -0,0 +1,9 @@
+/*
+ * This file is forked from the DefinitelyTyped project (https://github.com/DefinitelyTyped/DefinitelyTyped),
+ * and may include modifications made by Elasticsearch B.V.
+ * Elasticsearch B.V. licenses this file to you under the MIT License.
+ * See `packages/elastic-safer-lodash-set/LICENSE` for more information.
+ */
+
+import { assoc } from './index';
+export = assoc;
diff --git a/packages/elastic-safer-lodash-set/fp/assoc.js b/packages/elastic-safer-lodash-set/fp/assoc.js
new file mode 100644
index 0000000000000..851e11690ea35
--- /dev/null
+++ b/packages/elastic-safer-lodash-set/fp/assoc.js
@@ -0,0 +1,8 @@
+/*
+ * This file is forked from the lodash project (https://lodash.com/),
+ * and may include modifications made by Elasticsearch B.V.
+ * Elasticsearch B.V. licenses this file to you under the MIT License.
+ * See `packages/elastic-safer-lodash-set/LICENSE` for more information.
+ */
+
+module.exports = require('./set');
diff --git a/packages/elastic-safer-lodash-set/fp/assocPath.d.ts b/packages/elastic-safer-lodash-set/fp/assocPath.d.ts
new file mode 100644
index 0000000000000..76df38e98ff28
--- /dev/null
+++ b/packages/elastic-safer-lodash-set/fp/assocPath.d.ts
@@ -0,0 +1,9 @@
+/*
+ * This file is forked from the DefinitelyTyped project (https://github.com/DefinitelyTyped/DefinitelyTyped),
+ * and may include modifications made by Elasticsearch B.V.
+ * Elasticsearch B.V. licenses this file to you under the MIT License.
+ * See `packages/elastic-safer-lodash-set/LICENSE` for more information.
+ */
+
+import { assocPath } from './index';
+export = assocPath;
diff --git a/packages/elastic-safer-lodash-set/fp/assocPath.js b/packages/elastic-safer-lodash-set/fp/assocPath.js
new file mode 100644
index 0000000000000..851e11690ea35
--- /dev/null
+++ b/packages/elastic-safer-lodash-set/fp/assocPath.js
@@ -0,0 +1,8 @@
+/*
+ * This file is forked from the lodash project (https://lodash.com/),
+ * and may include modifications made by Elasticsearch B.V.
+ * Elasticsearch B.V. licenses this file to you under the MIT License.
+ * See `packages/elastic-safer-lodash-set/LICENSE` for more information.
+ */
+
+module.exports = require('./set');
diff --git a/packages/elastic-safer-lodash-set/fp/index.d.ts b/packages/elastic-safer-lodash-set/fp/index.d.ts
new file mode 100644
index 0000000000000..fcd7ff01e3cc8
--- /dev/null
+++ b/packages/elastic-safer-lodash-set/fp/index.d.ts
@@ -0,0 +1,225 @@
+/*
+ * This file is forked from the DefinitelyTyped project (https://github.com/DefinitelyTyped/DefinitelyTyped),
+ * and may include modifications made by Elasticsearch B.V.
+ * Elasticsearch B.V. licenses this file to you under the MIT License.
+ * See `packages/elastic-safer-lodash-set/LICENSE` for more information.
+ */
+
+import lodash = require('lodash');
+
+export = SaferLodashSet;
+export as namespace SaferLodashSet;
+
+declare const SaferLodashSet: SaferLodashSet.SaferLoDashStaticFp;
+declare namespace SaferLodashSet {
+ interface LodashSet {
+ (path: lodash.PropertyPath): LodashSet1x1;
+ (path: lodash.__, value: any): LodashSet1x2;
+ (path: lodash.PropertyPath, value: any): LodashSet1x3;
+ (path: lodash.__, value: lodash.__, object: T): LodashSet1x4;
+ (path: lodash.PropertyPath, value: lodash.__, object: T): LodashSet1x5;
+ (path: lodash.__, value: any, object: T): LodashSet1x6;
+ (path: lodash.PropertyPath, value: any, object: T): T;
+ (path: lodash.__, value: lodash.__, object: object): LodashSet2x4;
+ (path: lodash.PropertyPath, value: lodash.__, object: object): LodashSet2x5;
+ (path: lodash.__, value: any, object: object): LodashSet2x6;
+ (path: lodash.PropertyPath, value: any, object: object): TResult;
+ }
+ interface LodashSet1x1 {
+ (value: any): LodashSet1x3;
+ (value: lodash.__, object: T): LodashSet1x5;
+ (value: any, object: T): T;
+ (value: lodash.__, object: object): LodashSet2x5;
+ (value: any, object: object): TResult;
+ }
+ interface LodashSet1x2 {
+ (path: lodash.PropertyPath): LodashSet1x3;
+ (path: lodash.__, object: T): LodashSet1x6;
+ (path: lodash.PropertyPath, object: T): T;
+ (path: lodash.__, object: object): LodashSet2x6;
+ (path: lodash.PropertyPath, object: object): TResult;
+ }
+ interface LodashSet1x3 {
+ (object: T): T;
+ (object: object): TResult;
+ }
+ interface LodashSet1x4 {
+ (path: lodash.PropertyPath): LodashSet1x5;
+ (path: lodash.__, value: any): LodashSet1x6;
+ (path: lodash.PropertyPath, value: any): T;
+ }
+ type LodashSet1x5 = (value: any) => T;
+ type LodashSet1x6 = (path: lodash.PropertyPath) => T;
+ interface LodashSet2x4 {
+ (path: lodash.PropertyPath): LodashSet2x5;
+ (path: lodash.__, value: any): LodashSet2x6;
+ (path: lodash.PropertyPath, value: any): TResult;
+ }
+ type LodashSet2x5 = (value: any) => TResult;
+ type LodashSet2x6 = (path: lodash.PropertyPath) => TResult;
+
+ interface LodashSetWith {
+ (customizer: lodash.SetWithCustomizer): LodashSetWith1x1;
+ (customizer: lodash.__, path: lodash.PropertyPath): LodashSetWith1x2;
+ (
+ customizer: lodash.SetWithCustomizer,
+ path: lodash.PropertyPath
+ ): LodashSetWith1x3;
+ (customizer: lodash.__, path: lodash.__, value: any): LodashSetWith1x4;
+ (
+ customizer: lodash.SetWithCustomizer,
+ path: lodash.__,
+ value: any
+ ): LodashSetWith1x5;
+ (customizer: lodash.__, path: lodash.PropertyPath, value: any): LodashSetWith1x6;
+ (
+ customizer: lodash.SetWithCustomizer,
+ path: lodash.PropertyPath,
+ value: any
+ ): LodashSetWith1x7;
+ (
+ customizer: lodash.__,
+ path: lodash.__,
+ value: lodash.__,
+ object: T
+ ): LodashSetWith1x8;
+ (
+ customizer: lodash.SetWithCustomizer,
+ path: lodash.__,
+ value: lodash.__,
+ object: T
+ ): LodashSetWith1x9;
+ (
+ customizer: lodash.__,
+ path: lodash.PropertyPath,
+ value: lodash.__,
+ object: T
+ ): LodashSetWith1x10;
+ (
+ customizer: lodash.SetWithCustomizer,
+ path: lodash.PropertyPath,
+ value: lodash.__,
+ object: T
+ ): LodashSetWith1x11;
+ (
+ customizer: lodash.__,
+ path: lodash.__,
+ value: any,
+ object: T
+ ): LodashSetWith1x12;
+ (
+ customizer: lodash.SetWithCustomizer,
+ path: lodash.__,
+ value: any,
+ object: T
+ ): LodashSetWith1x13;
+ (
+ customizer: lodash.__,
+ path: lodash.PropertyPath,
+ value: any,
+ object: T
+ ): LodashSetWith1x14;
+ (
+ customizer: lodash.SetWithCustomizer,
+ path: lodash.PropertyPath,
+ value: any,
+ object: T
+ ): T;
+ }
+ interface LodashSetWith1x1 {
+ (path: lodash.PropertyPath): LodashSetWith1x3;
+ (path: lodash.__, value: any): LodashSetWith1x5;
+ (path: lodash.PropertyPath, value: any): LodashSetWith1x7;
+ (path: lodash.__, value: lodash.__, object: T): LodashSetWith1x9;
+ (path: lodash.PropertyPath, value: lodash.__, object: T): LodashSetWith1x11;
+ (path: lodash.__, value: any, object: T): LodashSetWith1x13;
+ (path: lodash.PropertyPath, value: any, object: T): T;
+ }
+ interface LodashSetWith1x2 {
+ (customizer: lodash.SetWithCustomizer): LodashSetWith1x3;
+ (customizer: lodash.__, value: any): LodashSetWith1x6;
+ (customizer: lodash.SetWithCustomizer, value: any): LodashSetWith1x7;
+ (customizer: lodash.__, value: lodash.__, object: T): LodashSetWith1x10;
+ (
+ customizer: lodash.SetWithCustomizer,
+ value: lodash.__,
+ object: T
+ ): LodashSetWith1x11;
+ (customizer: lodash.__, value: any, object: T): LodashSetWith1x14;
+ (customizer: lodash.SetWithCustomizer, value: any, object: T): T;
+ }
+ interface LodashSetWith1x3 {
+ (value: any): LodashSetWith1x7;
+ (value: lodash.__, object: T): LodashSetWith1x11;
+ (value: any, object: T): T;
+ }
+ interface LodashSetWith1x4 {
+ (customizer: lodash.SetWithCustomizer): LodashSetWith1x5;
+ (customizer: lodash.__, path: lodash.PropertyPath): LodashSetWith1x6;
+ (
+ customizer: lodash.SetWithCustomizer,
+ path: lodash.PropertyPath
+ ): LodashSetWith1x7;
+ (customizer: lodash.__, path: lodash.__, object: T): LodashSetWith1x12;
+ (
+ customizer: lodash.SetWithCustomizer,
+ path: lodash.__,
+ object: T
+ ): LodashSetWith1x13;
+ (
+ customizer: lodash.__,
+ path: lodash.PropertyPath,
+ object: T
+ ): LodashSetWith1x14;
+ (
+ customizer: lodash.SetWithCustomizer,
+ path: lodash.PropertyPath,
+ object: T
+ ): T;
+ }
+ interface LodashSetWith1x5 {
+ (path: lodash.PropertyPath): LodashSetWith1x7;
+ (path: lodash.__, object: T): LodashSetWith1x13;
+ (path: lodash.PropertyPath, object: T): T;
+ }
+ interface LodashSetWith1x6 {
+ (customizer: lodash.SetWithCustomizer): LodashSetWith1x7;
+ (customizer: lodash.__, object: T): LodashSetWith1x14;
+ (customizer: lodash.SetWithCustomizer, object: T): T;
+ }
+ type LodashSetWith1x7 = (object: T) => T;
+ interface LodashSetWith1x8 {
+ (customizer: lodash.SetWithCustomizer): LodashSetWith1x9;
+ (customizer: lodash.__, path: lodash.PropertyPath): LodashSetWith1x10;
+ (customizer: lodash.SetWithCustomizer, path: lodash.PropertyPath): LodashSetWith1x11;
+ (customizer: lodash.__, path: lodash.__, value: any): LodashSetWith1x12;
+ (customizer: lodash.SetWithCustomizer, path: lodash.__, value: any): LodashSetWith1x13;
+ (customizer: lodash.__, path: lodash.PropertyPath, value: any): LodashSetWith1x14;
+ (customizer: lodash.SetWithCustomizer, path: lodash.PropertyPath, value: any): T;
+ }
+ interface LodashSetWith1x9 {
+ (path: lodash.PropertyPath): LodashSetWith1x11;
+ (path: lodash.__, value: any): LodashSetWith1x13;
+ (path: lodash.PropertyPath, value: any): T;
+ }
+ interface LodashSetWith1x10 {
+ (customizer: lodash.SetWithCustomizer): LodashSetWith1x11;
+ (customizer: lodash.__, value: any): LodashSetWith1x14;
+ (customizer: lodash.SetWithCustomizer, value: any): T;
+ }
+ type LodashSetWith1x11 = (value: any) => T;
+ interface LodashSetWith1x12 {
+ (customizer: lodash.SetWithCustomizer): LodashSetWith1x13;
+ (customizer: lodash.__, path: lodash.PropertyPath): LodashSetWith1x14;
+ (customizer: lodash.SetWithCustomizer, path: lodash.PropertyPath): T;
+ }
+ type LodashSetWith1x13 = (path: lodash.PropertyPath) => T;
+ type LodashSetWith1x14 = (customizer: lodash.SetWithCustomizer) => T;
+
+ interface SaferLoDashStaticFp {
+ assoc: LodashSet;
+ assocPath: LodashSet;
+ set: LodashSet;
+ setWith: LodashSetWith;
+ }
+}
diff --git a/packages/elastic-safer-lodash-set/fp/index.js b/packages/elastic-safer-lodash-set/fp/index.js
new file mode 100644
index 0000000000000..7d9cdb099dfd7
--- /dev/null
+++ b/packages/elastic-safer-lodash-set/fp/index.js
@@ -0,0 +1,9 @@
+/*
+ * This file is forked from the lodash project (https://lodash.com/),
+ * and may include modifications made by Elasticsearch B.V.
+ * Elasticsearch B.V. licenses this file to you under the MIT License.
+ * See `packages/elastic-safer-lodash-set/LICENSE` for more information.
+ */
+
+exports.set = exports.assoc = exports.assocPath = require('./set');
+exports.setWith = require('./setWith');
diff --git a/packages/elastic-safer-lodash-set/fp/set.d.ts b/packages/elastic-safer-lodash-set/fp/set.d.ts
new file mode 100644
index 0000000000000..16bc98658bdcd
--- /dev/null
+++ b/packages/elastic-safer-lodash-set/fp/set.d.ts
@@ -0,0 +1,9 @@
+/*
+ * This file is forked from the DefinitelyTyped project (https://github.com/DefinitelyTyped/DefinitelyTyped),
+ * and may include modifications made by Elasticsearch B.V.
+ * Elasticsearch B.V. licenses this file to you under the MIT License.
+ * See `packages/elastic-safer-lodash-set/LICENSE` for more information.
+ */
+
+import { set } from './index';
+export = set;
diff --git a/packages/elastic-safer-lodash-set/fp/set.js b/packages/elastic-safer-lodash-set/fp/set.js
new file mode 100644
index 0000000000000..0fb48694d736d
--- /dev/null
+++ b/packages/elastic-safer-lodash-set/fp/set.js
@@ -0,0 +1,13 @@
+/*
+ * This file is forked from the lodash project (https://lodash.com/),
+ * and may include modifications made by Elasticsearch B.V.
+ * Elasticsearch B.V. licenses this file to you under the MIT License.
+ * See `packages/elastic-safer-lodash-set/LICENSE` for more information.
+ */
+
+/*eslint no-var:0 */
+var convert = require('lodash/fp/convert');
+var func = convert('set', require('../set'));
+
+func.placeholder = require('lodash/fp/placeholder');
+module.exports = func;
diff --git a/packages/elastic-safer-lodash-set/fp/setWith.d.ts b/packages/elastic-safer-lodash-set/fp/setWith.d.ts
new file mode 100644
index 0000000000000..556e702f59f0f
--- /dev/null
+++ b/packages/elastic-safer-lodash-set/fp/setWith.d.ts
@@ -0,0 +1,9 @@
+/*
+ * This file is forked from the DefinitelyTyped project (https://github.com/DefinitelyTyped/DefinitelyTyped),
+ * and may include modifications made by Elasticsearch B.V.
+ * Elasticsearch B.V. licenses this file to you under the MIT License.
+ * See `packages/elastic-safer-lodash-set/LICENSE` for more information.
+ */
+
+import { setWith } from './index';
+export = setWith;
diff --git a/packages/elastic-safer-lodash-set/fp/setWith.js b/packages/elastic-safer-lodash-set/fp/setWith.js
new file mode 100644
index 0000000000000..e477d4b4bc7ba
--- /dev/null
+++ b/packages/elastic-safer-lodash-set/fp/setWith.js
@@ -0,0 +1,13 @@
+/*
+ * This file is forked from the lodash project (https://lodash.com/),
+ * and may include modifications made by Elasticsearch B.V.
+ * Elasticsearch B.V. licenses this file to you under the MIT License.
+ * See `packages/elastic-safer-lodash-set/LICENSE` for more information.
+ */
+
+/*eslint no-var:0 */
+var convert = require('lodash/fp/convert');
+var func = convert('setWith', require('../setWith'));
+
+func.placeholder = require('lodash/fp/placeholder');
+module.exports = func;
diff --git a/packages/elastic-safer-lodash-set/index.d.ts b/packages/elastic-safer-lodash-set/index.d.ts
new file mode 100644
index 0000000000000..aaff01f11a7af
--- /dev/null
+++ b/packages/elastic-safer-lodash-set/index.d.ts
@@ -0,0 +1,64 @@
+/*
+ * This file is forked from the DefinitelyTyped project (https://github.com/DefinitelyTyped/DefinitelyTyped),
+ * and may include modifications made by Elasticsearch B.V.
+ * Elasticsearch B.V. licenses this file to you under the MIT License.
+ * See `packages/elastic-safer-lodash-set/LICENSE` for more information.
+ */
+
+export = SaferLodashSet;
+export as namespace SaferLodashSet;
+
+type Many = T | readonly T[];
+type PropertyName = string | number | symbol;
+type PropertyPath = Many;
+type SetWithCustomizer = (nsValue: any, key: string, nsObject: T) => any;
+
+declare const SaferLodashSet: SaferLodashSet.SaferLoDashStatic;
+declare namespace SaferLodashSet {
+ interface SaferLoDashStatic {
+ /**
+ * Sets the value at path of object. If a portion of path doesn’t exist it’s
+ * created. Arrays are created for missing index properties while objects
+ * are created for all other missing properties. Use SaferLodashSet.setWith
+ * to customize path creation.
+ *
+ * @param object The object to modify.
+ * @param path The path of the property to set.
+ * @param value The value to set.
+ * @return Returns object.
+ */
+ set(object: T, path: PropertyPath, value: any): T;
+ /**
+ * @see SaferLodashSet.set
+ */
+ set(object: object, path: PropertyPath, value: any): TResult;
+
+ /**
+ * This method is like SaferLodashSet.set except that it accepts customizer
+ * which is invoked to produce the objects of path. If customizer returns
+ * undefined path creation is handled by the method instead. The customizer
+ * is invoked with three arguments: (nsValue, key, nsObject).
+ *
+ * @param object The object to modify.
+ * @param path The path of the property to set.
+ * @param value The value to set.
+ * @param customizer The function to customize assigned values.
+ * @return Returns object.
+ */
+ setWith(
+ object: T,
+ path: PropertyPath,
+ value: any,
+ customizer?: SetWithCustomizer
+ ): T;
+ /**
+ * @see SaferLodashSet.setWith
+ */
+ setWith(
+ object: T,
+ path: PropertyPath,
+ value: any,
+ customizer?: SetWithCustomizer
+ ): TResult;
+ }
+}
diff --git a/packages/elastic-safer-lodash-set/index.js b/packages/elastic-safer-lodash-set/index.js
new file mode 100644
index 0000000000000..d9edb25476c12
--- /dev/null
+++ b/packages/elastic-safer-lodash-set/index.js
@@ -0,0 +1,9 @@
+/*
+ * This file is forked from the lodash project (https://lodash.com/),
+ * and may include modifications made by Elasticsearch B.V.
+ * Elasticsearch B.V. licenses this file to you under the MIT License.
+ * See `packages/elastic-safer-lodash-set/LICENSE` for more information.
+ */
+
+exports.set = require('./lodash/set');
+exports.setWith = require('./lodash/setWith');
diff --git a/packages/elastic-safer-lodash-set/lodash/_baseSet.js b/packages/elastic-safer-lodash-set/lodash/_baseSet.js
new file mode 100644
index 0000000000000..9cbf19808edd7
--- /dev/null
+++ b/packages/elastic-safer-lodash-set/lodash/_baseSet.js
@@ -0,0 +1,61 @@
+/*
+ * This file is forked from the lodash project (https://lodash.com/),
+ * and may include modifications made by Elasticsearch B.V.
+ * Elasticsearch B.V. licenses this file to you under the MIT License.
+ * See `packages/elastic-safer-lodash-set/LICENSE` for more information.
+ */
+
+/* eslint-disable */
+
+var assignValue = require('lodash/_assignValue'),
+ castPath = require('lodash/_castPath'),
+ isFunction = require('lodash/isFunction'),
+ isIndex = require('lodash/_isIndex'),
+ isObject = require('lodash/isObject'),
+ toKey = require('lodash/_toKey');
+
+/**
+ * The base implementation of `_.set`.
+ *
+ * @private
+ * @param {Object} object The object to modify.
+ * @param {Array|string} path The path of the property to set.
+ * @param {*} value The value to set.
+ * @param {Function} [customizer] The function to customize path creation.
+ * @returns {Object} Returns `object`.
+ */
+function baseSet(object, path, value, customizer) {
+ if (!isObject(object)) {
+ return object;
+ }
+ path = castPath(path, object);
+
+ var index = -1,
+ length = path.length,
+ lastIndex = length - 1,
+ nested = object;
+
+ while (nested != null && ++index < length) {
+ var key = toKey(path[index]),
+ newValue = value;
+
+ if (key == 'prototype' && isFunction(nested)) {
+ throw new Error('Illegal access of function prototype')
+ }
+
+ if (index != lastIndex) {
+ var objValue = hasOwnProperty.call(nested, key) ? nested[key] : undefined
+ newValue = customizer ? customizer(objValue, key, nested) : undefined;
+ if (newValue === undefined) {
+ newValue = isObject(objValue)
+ ? objValue
+ : (isIndex(path[index + 1]) ? [] : {});
+ }
+ }
+ assignValue(nested, key, newValue);
+ nested = nested[key];
+ }
+ return object;
+}
+
+module.exports = baseSet;
diff --git a/packages/elastic-safer-lodash-set/lodash/set.js b/packages/elastic-safer-lodash-set/lodash/set.js
new file mode 100644
index 0000000000000..740f7c926ee40
--- /dev/null
+++ b/packages/elastic-safer-lodash-set/lodash/set.js
@@ -0,0 +1,44 @@
+/*
+ * This file is forked from the lodash project (https://lodash.com/),
+ * and may include modifications made by Elasticsearch B.V.
+ * Elasticsearch B.V. licenses this file to you under the MIT License.
+ * See `packages/elastic-safer-lodash-set/LICENSE` for more information.
+ */
+
+/* eslint-disable */
+
+var baseSet = require('./_baseSet');
+
+/**
+ * Sets the value at `path` of `object`. If a portion of `path` doesn't exist,
+ * it's created. Arrays are created for missing index properties while objects
+ * are created for all other missing properties. Use `_.setWith` to customize
+ * `path` creation.
+ *
+ * **Note:** This method mutates `object`.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.7.0
+ * @category Object
+ * @param {Object} object The object to modify.
+ * @param {Array|string} path The path of the property to set.
+ * @param {*} value The value to set.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * var object = { 'a': [{ 'b': { 'c': 3 } }] };
+ *
+ * _.set(object, 'a[0].b.c', 4);
+ * console.log(object.a[0].b.c);
+ * // => 4
+ *
+ * _.set(object, ['x', '0', 'y', 'z'], 5);
+ * console.log(object.x[0].y.z);
+ * // => 5
+ */
+function set(object, path, value) {
+ return object == null ? object : baseSet(object, path, value);
+}
+
+module.exports = set;
diff --git a/packages/elastic-safer-lodash-set/lodash/setWith.js b/packages/elastic-safer-lodash-set/lodash/setWith.js
new file mode 100644
index 0000000000000..0ac4f4c9cf39f
--- /dev/null
+++ b/packages/elastic-safer-lodash-set/lodash/setWith.js
@@ -0,0 +1,41 @@
+/*
+ * This file is forked from the lodash project (https://lodash.com/),
+ * and may include modifications made by Elasticsearch B.V.
+ * Elasticsearch B.V. licenses this file to you under the MIT License.
+ * See `packages/elastic-safer-lodash-set/LICENSE` for more information.
+ */
+
+/* eslint-disable */
+
+var baseSet = require('./_baseSet');
+
+/**
+ * This method is like `_.set` except that it accepts `customizer` which is
+ * invoked to produce the objects of `path`. If `customizer` returns `undefined`
+ * path creation is handled by the method instead. The `customizer` is invoked
+ * with three arguments: (nsValue, key, nsObject).
+ *
+ * **Note:** This method mutates `object`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Object
+ * @param {Object} object The object to modify.
+ * @param {Array|string} path The path of the property to set.
+ * @param {*} value The value to set.
+ * @param {Function} [customizer] The function to customize assigned values.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * var object = {};
+ *
+ * _.setWith(object, '[0][1]', 'a', Object);
+ * // => { '0': { '1': 'a' } }
+ */
+function setWith(object, path, value, customizer) {
+ customizer = typeof customizer == 'function' ? customizer : undefined;
+ return object == null ? object : baseSet(object, path, value, customizer);
+}
+
+module.exports = setWith;
diff --git a/packages/elastic-safer-lodash-set/package.json b/packages/elastic-safer-lodash-set/package.json
new file mode 100644
index 0000000000000..f0f425661f605
--- /dev/null
+++ b/packages/elastic-safer-lodash-set/package.json
@@ -0,0 +1,49 @@
+{
+ "name": "@elastic/safer-lodash-set",
+ "version": "0.0.0",
+ "description": "A safer version of the lodash set and setWith functions",
+ "main": "index.js",
+ "types": "index.d.ts",
+ "dependencies": {},
+ "devDependencies": {
+ "dependency-check": "^4.1.0",
+ "tape": "^5.0.1",
+ "tsd": "^0.13.1"
+ },
+ "peerDependencies": {
+ "lodash": "4.x"
+ },
+ "scripts": {
+ "lint": "dependency-check --no-dev package.json set.js setWith.js fp/*.js",
+ "test": "npm run lint && tape test/*.js && npm run test:types",
+ "test:types": "./scripts/tsd.sh",
+ "update": "./scripts/update.sh",
+ "save_state": "./scripts/save_state.sh"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/elastic/kibana.git"
+ },
+ "keywords": [
+ "lodash",
+ "security",
+ "set",
+ "setWith",
+ "prototype",
+ "pollution"
+ ],
+ "author": "Thomas Watson (https://twitter.com/wa7son)",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/elastic/kibana/issues"
+ },
+ "homepage": "https://github.com/elastic/kibana/tree/master/packages/safer-lodash-set#readme",
+ "standard": {
+ "ignore": [
+ "/lodash/"
+ ]
+ },
+ "tsd": {
+ "directory": "test"
+ }
+}
diff --git a/packages/elastic-safer-lodash-set/scripts/_get_lodash.sh b/packages/elastic-safer-lodash-set/scripts/_get_lodash.sh
new file mode 100755
index 0000000000000..50d3edaf34717
--- /dev/null
+++ b/packages/elastic-safer-lodash-set/scripts/_get_lodash.sh
@@ -0,0 +1,15 @@
+#!/usr/bin/env bash
+
+# Elasticsearch B.V licenses this file to you under the MIT License.
+# See `packages/elastic-safer-lodash-set/LICENSE` for more information.
+
+clean_up () {
+ exit_code=$?
+ rm -fr .tmp
+ exit $exit_code
+}
+trap clean_up EXIT
+
+# Get a temporary copy of the latest v4 lodash
+rm -fr .tmp
+npm install --no-fund --ignore-scripts --no-audit --loglevel error --prefix ./.tmp lodash@4 > /dev/null
diff --git a/packages/elastic-safer-lodash-set/scripts/license-header.txt b/packages/elastic-safer-lodash-set/scripts/license-header.txt
new file mode 100644
index 0000000000000..4d0aedf74bb0f
--- /dev/null
+++ b/packages/elastic-safer-lodash-set/scripts/license-header.txt
@@ -0,0 +1,7 @@
+/*
+ * This file is forked from the lodash project (https://lodash.com/),
+ * and may include modifications made by Elasticsearch B.V.
+ * Elasticsearch B.V. licenses this file to you under the MIT License.
+ * See `packages/elastic-safer-lodash-set/LICENSE` for more information.
+ */
+
diff --git a/packages/elastic-safer-lodash-set/scripts/patches/_baseSet.js.patch b/packages/elastic-safer-lodash-set/scripts/patches/_baseSet.js.patch
new file mode 100644
index 0000000000000..c7cf2041355d0
--- /dev/null
+++ b/packages/elastic-safer-lodash-set/scripts/patches/_baseSet.js.patch
@@ -0,0 +1,31 @@
+1,5c1,15
+< var assignValue = require('./_assignValue'),
+< castPath = require('./_castPath'),
+< isIndex = require('./_isIndex'),
+< isObject = require('./isObject'),
+< toKey = require('./_toKey');
+---
+> /*
+> * This file is forked from the lodash project (https://lodash.com/),
+> * and may include modifications made by Elasticsearch B.V.
+> * Elasticsearch B.V. licenses this file to you under the MIT License.
+> * See `packages/elastic-safer-lodash-set/LICENSE` for more information.
+> */
+>
+> /* eslint-disable */
+>
+> var assignValue = require('lodash/_assignValue'),
+> castPath = require('lodash/_castPath'),
+> isFunction = require('lodash/isFunction'),
+> isIndex = require('lodash/_isIndex'),
+> isObject = require('lodash/isObject'),
+> toKey = require('lodash/_toKey');
+31a42,45
+> if (key == 'prototype' && isFunction(nested)) {
+> throw new Error('Illegal access of function prototype')
+> }
+>
+33c47
+< var objValue = nested[key];
+---
+> var objValue = hasOwnProperty.call(nested, key) ? nested[key] : undefined
diff --git a/packages/elastic-safer-lodash-set/scripts/save_state.sh b/packages/elastic-safer-lodash-set/scripts/save_state.sh
new file mode 100755
index 0000000000000..ead99c3d1de48
--- /dev/null
+++ b/packages/elastic-safer-lodash-set/scripts/save_state.sh
@@ -0,0 +1,18 @@
+#!/usr/bin/env bash
+
+# Elasticsearch B.V licenses this file to you under the MIT License.
+# See `packages/elastic-safer-lodash-set/LICENSE` for more information.
+
+set -e
+
+source ./scripts/_get_lodash.sh
+
+modified_lodash_files=(_baseSet.js)
+
+# Create fresh patch files for each of the modified files
+for file in "${modified_lodash_files[@]}"
+do
+ diff ".tmp/node_modules/lodash/$file" "lodash/$file" > "scripts/patches/$file.patch" || true
+done
+
+echo "State updated!"
diff --git a/packages/elastic-safer-lodash-set/scripts/tsd.sh b/packages/elastic-safer-lodash-set/scripts/tsd.sh
new file mode 100755
index 0000000000000..4572367df415d
--- /dev/null
+++ b/packages/elastic-safer-lodash-set/scripts/tsd.sh
@@ -0,0 +1,17 @@
+#!/usr/bin/env bash
+
+# Elasticsearch B.V licenses this file to you under the MIT License.
+# See `packages/elastic-safer-lodash-set/LICENSE` for more information.
+
+# tsd will get confused if it finds a tsconfig.json file in the project
+# directory and start to scan the entirety of Kibana. We don't want that.
+mv tsconfig.json tsconfig.tmp
+
+clean_up () {
+ exit_code=$?
+ mv tsconfig.tmp tsconfig.json
+ exit $exit_code
+}
+trap clean_up EXIT
+
+./node_modules/.bin/tsd
diff --git a/packages/elastic-safer-lodash-set/scripts/update.sh b/packages/elastic-safer-lodash-set/scripts/update.sh
new file mode 100755
index 0000000000000..58fd89eb43e33
--- /dev/null
+++ b/packages/elastic-safer-lodash-set/scripts/update.sh
@@ -0,0 +1,37 @@
+#!/usr/bin/env bash
+
+# Elasticsearch B.V licenses this file to you under the MIT License.
+# See `packages/elastic-safer-lodash-set/LICENSE` for more information.
+
+set -e
+
+source ./scripts/_get_lodash.sh
+
+all_files=$(cd lodash && ls)
+modified_lodash_files=(_baseSet.js)
+
+# Get fresh copies of all the files that was originally copied from lodash,
+# expect the ones in the whitelist
+for file in $all_files
+do
+ if [[ ! "${modified_lodash_files[@]}" =~ "${file}" ]]
+ then
+ cat scripts/license-header.txt > "lodash/$file"
+ printf "/* eslint-disable */\n\n" >> "lodash/$file"
+ cat ".tmp/node_modules/lodash/$file" >> "lodash/$file"
+ fi
+done
+
+# Check if there's changes to the patched files
+for file in "${modified_lodash_files[@]}"
+do
+ diff ".tmp/node_modules/lodash/$file" "lodash/$file" > ".tmp/$file.patch" || true
+ if [[ $(diff ".tmp/$file.patch" "scripts/patches/$file.patch") ]]; then
+ echo "WARNING: The modified file $file have changed in a newer version of lodash, but was not updated:"
+ echo "------------------------------------------------------------------------"
+ diff ".tmp/$file.patch" "scripts/patches/$file.patch" || true
+ echo "------------------------------------------------------------------------"
+ fi
+done
+
+echo "Update complete!"
diff --git a/packages/elastic-safer-lodash-set/set.d.ts b/packages/elastic-safer-lodash-set/set.d.ts
new file mode 100644
index 0000000000000..16bc98658bdcd
--- /dev/null
+++ b/packages/elastic-safer-lodash-set/set.d.ts
@@ -0,0 +1,9 @@
+/*
+ * This file is forked from the DefinitelyTyped project (https://github.com/DefinitelyTyped/DefinitelyTyped),
+ * and may include modifications made by Elasticsearch B.V.
+ * Elasticsearch B.V. licenses this file to you under the MIT License.
+ * See `packages/elastic-safer-lodash-set/LICENSE` for more information.
+ */
+
+import { set } from './index';
+export = set;
diff --git a/packages/elastic-safer-lodash-set/set.js b/packages/elastic-safer-lodash-set/set.js
new file mode 100644
index 0000000000000..6977062908549
--- /dev/null
+++ b/packages/elastic-safer-lodash-set/set.js
@@ -0,0 +1,8 @@
+/*
+ * This file is forked from the lodash project (https://lodash.com/),
+ * and may include modifications made by Elasticsearch B.V.
+ * Elasticsearch B.V. licenses this file to you under the MIT License.
+ * See `packages/elastic-safer-lodash-set/LICENSE` for more information.
+ */
+
+module.exports = require('./lodash/set');
diff --git a/packages/elastic-safer-lodash-set/setWith.d.ts b/packages/elastic-safer-lodash-set/setWith.d.ts
new file mode 100644
index 0000000000000..556e702f59f0f
--- /dev/null
+++ b/packages/elastic-safer-lodash-set/setWith.d.ts
@@ -0,0 +1,9 @@
+/*
+ * This file is forked from the DefinitelyTyped project (https://github.com/DefinitelyTyped/DefinitelyTyped),
+ * and may include modifications made by Elasticsearch B.V.
+ * Elasticsearch B.V. licenses this file to you under the MIT License.
+ * See `packages/elastic-safer-lodash-set/LICENSE` for more information.
+ */
+
+import { setWith } from './index';
+export = setWith;
diff --git a/packages/elastic-safer-lodash-set/setWith.js b/packages/elastic-safer-lodash-set/setWith.js
new file mode 100644
index 0000000000000..aafa8a4db4be6
--- /dev/null
+++ b/packages/elastic-safer-lodash-set/setWith.js
@@ -0,0 +1,8 @@
+/*
+ * This file is forked from the lodash project (https://lodash.com/),
+ * and may include modifications made by Elasticsearch B.V.
+ * Elasticsearch B.V. licenses this file to you under the MIT License.
+ * See `packages/elastic-safer-lodash-set/LICENSE` for more information.
+ */
+
+module.exports = require('./lodash/setWith');
diff --git a/packages/elastic-safer-lodash-set/test/fp.test-d.ts b/packages/elastic-safer-lodash-set/test/fp.test-d.ts
new file mode 100644
index 0000000000000..7a1d6601b5e26
--- /dev/null
+++ b/packages/elastic-safer-lodash-set/test/fp.test-d.ts
@@ -0,0 +1,85 @@
+/*
+ * Elasticsearch B.V licenses this file to you under the MIT License.
+ * See `packages/elastic-safer-lodash-set/LICENSE` for more information.
+ */
+
+import { expectType } from 'tsd';
+import { set, setWith, assoc, assocPath } from '../fp';
+
+const someObj: object = {};
+const anyValue: any = 'any value';
+
+function customizer(value: any, key: string, obj: object) {
+ expectType(value);
+ expectType(key);
+ expectType