Harden console functions (#171367)

## Summary

This PR overrides console functions only in production, in order to
sanitize input parameters for any potential calls made to the global
console from Kibana's dependencies.

This initial implementation overrides the `debug`, `error`, `info`,
`log`, `trace`, and `warn` functions, and only sanitizes string inputs.
Future updates may expand this to handle other types, or strings nested
in objects.

The unmodified console methods are now exposed internally in Kibana as
`unsafeConsole`. Where needed for formatting (log appenders, core
logger), calls to the global console have been replaced by
`unsafeConsole`. This PR also adds a new es linting rule to disallow
calls to `unsafeConsole` unless `eslint-disable-next-line
@kbn/eslint/no_unsafe_console` is used.

### Testing
Not sure how we could test this. The overrides are only enabled when
running in a true production environment (e.g. docker) by checking
`process.env.NODE_ENV`.

I was able to manually test by adding additional console output denoting
when the console functions were being overriden or not.

Closes https://github.com/elastic/kibana-team/issues/664
Closes #176340

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Jeramy Soucy 2024-02-09 09:13:52 -05:00 committed by GitHub
parent c5819dc09e
commit 2627f48d95
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
34 changed files with 379 additions and 47 deletions

1
.github/CODEOWNERS vendored
View file

@ -674,6 +674,7 @@ packages/kbn-search-index-documents @elastic/enterprise-search-frontend
packages/kbn-search-response-warnings @elastic/kibana-data-discovery
x-pack/plugins/searchprofiler @elastic/platform-deployment-management
x-pack/test/security_api_integration/packages/helpers @elastic/kibana-security
packages/kbn-security-hardening @elastic/kibana-security
x-pack/plugins/security @elastic/kibana-security
x-pack/packages/security/plugin_types_common @elastic/kibana-security
x-pack/packages/security/plugin_types_public @elastic/kibana-security

View file

@ -676,6 +676,7 @@
"@kbn/search-index-documents": "link:packages/kbn-search-index-documents",
"@kbn/search-response-warnings": "link:packages/kbn-search-response-warnings",
"@kbn/searchprofiler-plugin": "link:x-pack/plugins/searchprofiler",
"@kbn/security-hardening": "link:packages/kbn-security-hardening",
"@kbn/security-plugin": "link:x-pack/plugins/security",
"@kbn/security-plugin-types-common": "link:x-pack/packages/security/plugin_types_common",
"@kbn/security-plugin-types-public": "link:x-pack/packages/security/plugin_types_public",

View file

@ -7,16 +7,17 @@
*/
import type { LogRecord } from '@kbn/logging';
import { unsafeConsole } from '@kbn/security-hardening';
import { createLogger } from './logger';
describe('createLogger', () => {
// Calling `.mockImplementation` on all of them to avoid jest logging the console usage
const logErrorSpy = jest.spyOn(console, 'error').mockImplementation();
const logWarnSpy = jest.spyOn(console, 'warn').mockImplementation();
const logInfoSpy = jest.spyOn(console, 'info').mockImplementation();
const logDebugSpy = jest.spyOn(console, 'debug').mockImplementation();
const logTraceSpy = jest.spyOn(console, 'trace').mockImplementation();
const logLogSpy = jest.spyOn(console, 'log').mockImplementation();
const logErrorSpy = jest.spyOn(unsafeConsole, 'error').mockImplementation();
const logWarnSpy = jest.spyOn(unsafeConsole, 'warn').mockImplementation();
const logInfoSpy = jest.spyOn(unsafeConsole, 'info').mockImplementation();
const logDebugSpy = jest.spyOn(unsafeConsole, 'debug').mockImplementation();
const logTraceSpy = jest.spyOn(unsafeConsole, 'trace').mockImplementation();
const logLogSpy = jest.spyOn(unsafeConsole, 'log').mockImplementation();
beforeEach(() => {
jest.clearAllMocks();

View file

@ -7,6 +7,7 @@
*/
import type { Logger } from '@kbn/logging';
import { unsafeConsole } from '@kbn/security-hardening';
/**
* Create custom logger until we have a proper logging solution: https://github.com/elastic/kibana/issues/33796
@ -16,20 +17,20 @@ export function createLogger(isDev: boolean): Logger {
// TODO: Replace with a core logger once we implement it in https://github.com/elastic/kibana/issues/33796
// For now, it logs only in dev mode
const logger: Logger = {
// eslint-disable-next-line no-console
fatal: (...args) => (isDev ? console.error(...args) : void 0),
// eslint-disable-next-line no-console
error: (...args) => (isDev ? console.error(...args) : void 0),
// eslint-disable-next-line no-console
warn: (...args) => (isDev ? console.warn(...args) : void 0),
// eslint-disable-next-line no-console
info: (...args) => (isDev ? console.info(...args) : void 0),
// eslint-disable-next-line no-console
debug: (...args) => (isDev ? console.debug(...args) : void 0),
// eslint-disable-next-line no-console
trace: (...args) => (isDev ? console.trace(...args) : void 0),
// eslint-disable-next-line no-console
log: (...args) => (isDev ? console.log(...args) : void 0),
// eslint-disable-next-line @kbn/eslint/no_unsafe_console
fatal: (...args) => (isDev ? unsafeConsole.error(...args) : void 0),
// eslint-disable-next-line @kbn/eslint/no_unsafe_console
error: (...args) => (isDev ? unsafeConsole.error(...args) : void 0),
// eslint-disable-next-line @kbn/eslint/no_unsafe_console
warn: (...args) => (isDev ? unsafeConsole.warn(...args) : void 0),
// eslint-disable-next-line @kbn/eslint/no_unsafe_console
info: (...args) => (isDev ? unsafeConsole.info(...args) : void 0),
// eslint-disable-next-line @kbn/eslint/no_unsafe_console
debug: (...args) => (isDev ? unsafeConsole.debug(...args) : void 0),
// eslint-disable-next-line @kbn/eslint/no_unsafe_console
trace: (...args) => (isDev ? unsafeConsole.trace(...args) : void 0),
// eslint-disable-next-line @kbn/eslint/no_unsafe_console
log: (...args) => (isDev ? unsafeConsole.log(...args) : void 0),
isLevelEnabled: () => true,
get: () => logger,
};

View file

@ -13,7 +13,8 @@
"@kbn/core-injected-metadata-browser-internal",
"@kbn/core-analytics-browser",
"@kbn/core-base-browser-mocks",
"@kbn/core-injected-metadata-browser-mocks"
"@kbn/core-injected-metadata-browser-mocks",
"@kbn/security-hardening"
],
"exclude": ["target/**/*"]
}

View file

@ -7,10 +7,11 @@
*/
import { LogRecord, LogLevel } from '@kbn/logging';
import { unsafeConsole } from '@kbn/security-hardening';
import { ConsoleAppender } from './console_appender';
test('`append()` correctly formats records and pushes them to console.', () => {
jest.spyOn(global.console, 'log').mockImplementation(() => {
jest.spyOn(unsafeConsole, 'log').mockImplementation(() => {
// noop
});
@ -47,10 +48,7 @@ test('`append()` correctly formats records and pushes them to console.', () => {
for (const record of records) {
appender.append(record);
// eslint-disable-next-line no-console
expect(console.log).toHaveBeenCalledWith(`mock-${JSON.stringify(record)}`);
expect(unsafeConsole.log).toHaveBeenCalledWith(`mock-${JSON.stringify(record)}`);
}
// eslint-disable-next-line no-console
expect(console.log).toHaveBeenCalledTimes(records.length);
expect(unsafeConsole.log).toHaveBeenCalledTimes(records.length);
});

View file

@ -7,6 +7,7 @@
*/
import type { Layout, LogRecord, DisposableAppender } from '@kbn/logging';
import { unsafeConsole } from '@kbn/security-hardening';
/**
*
@ -25,8 +26,8 @@ export class ConsoleAppender implements DisposableAppender {
* @param record `LogRecord` instance to be logged.
*/
public append(record: LogRecord) {
// eslint-disable-next-line no-console
console.log(this.layout.format(record));
// eslint-disable-next-line @kbn/eslint/no_unsafe_console
unsafeConsole.log(this.layout.format(record));
}
/**

View file

@ -6,6 +6,7 @@
* Side Public License, v 1.
*/
import { unsafeConsole } from '@kbn/security-hardening';
import { BrowserLoggingSystem } from './logging_system';
describe('', () => {
@ -15,7 +16,7 @@ describe('', () => {
let loggingSystem: BrowserLoggingSystem;
beforeEach(() => {
mockConsoleLog = jest.spyOn(global.console, 'log').mockReturnValue(undefined);
mockConsoleLog = jest.spyOn(unsafeConsole, 'log').mockReturnValue(undefined);
jest.spyOn<any, any>(global, 'Date').mockImplementation(() => timestamp);
loggingSystem = new BrowserLoggingSystem({ logLevel: 'warn' });
});

View file

@ -12,7 +12,8 @@
],
"kbn_references": [
"@kbn/logging",
"@kbn/core-logging-common-internal"
"@kbn/core-logging-common-internal",
"@kbn/security-hardening"
],
"exclude": [
"target/**/*",

View file

@ -19,6 +19,7 @@ jest.mock('../../layouts/layouts', () => {
});
import { LogRecord, LogLevel } from '@kbn/logging';
import { unsafeConsole } from '@kbn/security-hardening';
import { ConsoleAppender } from './console_appender';
test('`configSchema` creates correct schema.', () => {
@ -37,7 +38,7 @@ test('`configSchema` creates correct schema.', () => {
});
test('`append()` correctly formats records and pushes them to console.', () => {
jest.spyOn(global.console, 'log').mockImplementation(() => {
jest.spyOn(unsafeConsole, 'log').mockImplementation(() => {
// noop
});
@ -74,10 +75,7 @@ test('`append()` correctly formats records and pushes them to console.', () => {
for (const record of records) {
appender.append(record);
// eslint-disable-next-line no-console
expect(console.log).toHaveBeenCalledWith(`mock-${JSON.stringify(record)}`);
expect(unsafeConsole.log).toHaveBeenCalledWith(`mock-${JSON.stringify(record)}`);
}
// eslint-disable-next-line no-console
expect(console.log).toHaveBeenCalledTimes(records.length);
expect(unsafeConsole.log).toHaveBeenCalledTimes(records.length);
});

View file

@ -8,6 +8,7 @@
import { schema } from '@kbn/config-schema';
import type { Layout, LogRecord, DisposableAppender } from '@kbn/logging';
import { unsafeConsole } from '@kbn/security-hardening';
import { Layouts } from '../../layouts/layouts';
const { literal, object } = schema;
@ -34,8 +35,8 @@ export class ConsoleAppender implements DisposableAppender {
* @param record `LogRecord` instance to be logged.
*/
public append(record: LogRecord) {
// eslint-disable-next-line no-console
console.log(this.layout.format(record));
// eslint-disable-next-line @kbn/eslint/no_unsafe_console
unsafeConsole.log(this.layout.format(record));
}
/**

View file

@ -18,10 +18,11 @@ const mockCreateWriteStream = createWriteStream as unknown as jest.Mock<typeof c
import { LoggingSystem, config } from '..';
import { EcsVersion } from '@kbn/ecs';
import { unsafeConsole } from '@kbn/security-hardening';
let system: LoggingSystem;
beforeEach(() => {
mockConsoleLog = jest.spyOn(global.console, 'log').mockReturnValue(undefined);
mockConsoleLog = jest.spyOn(unsafeConsole, 'log').mockReturnValue(undefined);
jest.spyOn<any, any>(global, 'Date').mockImplementation(() => timestamp);
jest.spyOn(process, 'uptime').mockReturnValue(10);
system = new LoggingSystem();

View file

@ -22,6 +22,7 @@
"@kbn/utility-types-jest",
"@kbn/utility-types",
"@kbn/ecs",
"@kbn/security-hardening",
],
"exclude": [
"target/**/*",

View file

@ -273,6 +273,7 @@ module.exports = {
'@kbn/eslint/no_trailing_import_slash': 'error',
'@kbn/eslint/no_constructor_args_in_property_initializers': 'error',
'@kbn/eslint/no_this_in_property_initializers': 'error',
'@kbn/eslint/no_unsafe_console': 'error',
'@kbn/imports/no_unresolvable_imports': 'error',
'@kbn/imports/uniform_imports': 'error',
'@kbn/imports/no_unused_imports': 'error',

View file

@ -103,4 +103,8 @@ module.exports = {
}
]
}
```
```
## no_unsafe_console
Disables the usage of kbn-security-hardening/console/unsafeConsole.

View file

@ -17,5 +17,6 @@ module.exports = {
no_trailing_import_slash: require('./rules/no_trailing_import_slash'),
no_constructor_args_in_property_initializers: require('./rules/no_constructor_args_in_property_initializers'),
no_this_in_property_initializers: require('./rules/no_this_in_property_initializers'),
no_unsafe_console: require('./rules/no_unsafe_console'),
},
};

View file

@ -0,0 +1,71 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
const tsEstree = require('@typescript-eslint/typescript-estree');
const esTypes = tsEstree.AST_NODE_TYPES;
/** @typedef {import("eslint").Rule.RuleModule} Rule */
/** @typedef {import("@typescript-eslint/typescript-estree").TSESTree.Node} Node */
/** @typedef {import("@typescript-eslint/typescript-estree").TSESTree.CallExpression} CallExpression */
/** @typedef {import("@typescript-eslint/typescript-estree").TSESTree.CallExpression} VariableDeclarator */
const ERROR_MSG = 'Unexpected unsafeConsole statement.';
/**
* @param {CallExpression} node
*/
const isUnsafeConsoleCall = (node) => {
return (
node.callee.type === esTypes.MemberExpression &&
node.callee.property.type === esTypes.Identifier &&
node.callee.object.name === 'unsafeConsole' &&
node.callee.property.name
);
};
/**
* @param {VariableDeclarator} node
*/
const isUnsafeConsoleObjectPatternDeclarator = (node) => {
return (
node.id.type === esTypes.ObjectPattern &&
node.init &&
node.init.type === esTypes.Identifier &&
node.init.name === 'unsafeConsole'
);
};
/** @type {Rule} */
module.exports = {
meta: {
fixable: 'code',
schema: [],
},
create: (context) => ({
CallExpression(_) {
const node = /** @type {CallExpression} */ (_);
if (isUnsafeConsoleCall(node)) {
context.report({
message: ERROR_MSG,
loc: node.callee.loc,
});
}
},
VariableDeclarator(_) {
const node = /** @type {VariableDeclarator} */ (_);
if (isUnsafeConsoleObjectPatternDeclarator(node)) {
context.report({
message: ERROR_MSG,
loc: node.init.loc,
});
}
},
}),
};

View file

@ -0,0 +1,121 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
const { RuleTester } = require('eslint');
const rule = require('./no_unsafe_console');
const dedent = require('dedent');
const ruleTester = new RuleTester({
parser: require.resolve('@typescript-eslint/parser'),
parserOptions: {
sourceType: 'module',
ecmaVersion: 2018,
},
});
ruleTester.run('@kbn/eslint/no_unsafe_console', rule, {
valid: [
{
code: dedent`
unsafeConsole
`,
},
],
invalid: [
{
code: dedent`
unsafeConsole.debug('something to debug')
`,
errors: [
{
line: 1,
message: 'Unexpected unsafeConsole statement.',
},
],
},
{
code: dedent`
unsafeConsole.error()
`,
errors: [
{
line: 1,
message: 'Unexpected unsafeConsole statement.',
},
],
},
{
code: dedent`
unsafeConsole.info('some info')
`,
errors: [
{
line: 1,
message: 'Unexpected unsafeConsole statement.',
},
],
},
{
code: dedent`
unsafeConsole.log('something to log')
`,
errors: [
{
line: 1,
message: 'Unexpected unsafeConsole statement.',
},
],
},
{
code: dedent`
unsafeConsole.trace()
`,
errors: [
{
line: 1,
message: 'Unexpected unsafeConsole statement.',
},
],
},
{
code: dedent`
unsafeConsole.warn('something to warn')
`,
errors: [
{
line: 1,
message: 'Unexpected unsafeConsole statement.',
},
],
},
{
code: dedent`
unsafeConsole.anyOtherMethodName()
`,
errors: [
{
line: 1,
message: 'Unexpected unsafeConsole statement.',
},
],
},
{
code: dedent`
const { debug } = unsafeConsole
debug('something to debug')
`,
errors: [
{
line: 1,
message: 'Unexpected unsafeConsole statement.',
},
],
},
],
});

View file

@ -0,0 +1,7 @@
# @kbn/security-hardening
A package counterpart of `src/setup_node_env/harden` - containing overrides, utilities, and tools to reduce potential vulnerability.
## console
When running in production mode (`process.env.NODE_ENV === 'production'`), global console methods `debug`, `error`, `info`, `log`, `trace`, and `warn` are overridden to implement input sanitization. The export `unsafeConsole` provides access to the unmodified global console methods.

View file

@ -0,0 +1,69 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
/* eslint-disable no-console */
// From https://www.ascii-code.com/characters/control-characters,
// but explicitly allowing the range \u0008-\u000F (line breaks, tabs, etc.)
const CONTROL_CHAR_REGEXP = new RegExp('[\\u0000-\\u0007\\u0010-\\u001F]', 'g');
export const unsafeConsole = {
debug: console.debug.bind(console),
error: console.error.bind(console),
info: console.info.bind(console),
log: console.log.bind(console),
trace: console.trace.bind(console),
warn: console.warn.bind(console),
};
function callWithSanitizedArgs(func: Function, ...args: any[]) {
const cleanedArgs = args.map(function (arg) {
if (typeof arg !== 'string') return arg;
return escapeControlChars(arg);
});
func.apply(console, cleanedArgs);
}
if (process.env.NODE_ENV === 'production') {
console.log('Native global console methods have been overridden in production environment.');
console.debug = function (...args) {
callWithSanitizedArgs(unsafeConsole.debug, ...args);
};
console.error = function (...args) {
callWithSanitizedArgs(unsafeConsole.error, ...args);
};
console.info = function (...args) {
callWithSanitizedArgs(unsafeConsole.info, ...args);
};
console.log = function (...args) {
callWithSanitizedArgs(unsafeConsole.log, ...args);
};
console.trace = function (...args) {
callWithSanitizedArgs(unsafeConsole.trace, ...args);
};
console.warn = function (...args) {
callWithSanitizedArgs(unsafeConsole.warn, ...args);
};
}
function escapeControlChars(input: string) {
return input.replace(
CONTROL_CHAR_REGEXP,
// Escaping control chars via JSON.stringify to maintain consistency with `meta` and the JSON layout.
// This way, post analysis of the logs is easier as we can search the same patterns.
// Our benchmark didn't show a big difference in performance between custom-escaping vs. JSON.stringify one.
// The slice is removing the double-quotes.
(substr) => JSON.stringify(substr).slice(1, -1)
);
}

View file

@ -0,0 +1,9 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
export { unsafeConsole } from './console';

View file

@ -0,0 +1,5 @@
{
"type": "shared-common",
"id": "@kbn/security-hardening",
"owner": "@elastic/kibana-security"
}

View file

@ -0,0 +1,6 @@
{
"name": "@kbn/security-hardening",
"private": true,
"version": "1.0.0",
"license": "SSPL-1.0 OR Elastic License 2.0"
}

View file

@ -0,0 +1,16 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "target/types",
"types": [
"node"
]
},
"include": [
"**/*.ts",
],
"exclude": [
"target/**/*"
],
"kbn_references": []
}

View file

@ -11,6 +11,7 @@ import {
type TestElasticsearchUtils,
type TestKibanaUtils,
} from '@kbn/core-test-helpers-kbn-server';
import { unsafeConsole } from '@kbn/security-hardening';
describe('Error logging', () => {
describe('ES client errors', () => {
@ -19,7 +20,7 @@ describe('Error logging', () => {
let kibanaServer: TestKibanaUtils;
beforeAll(async () => {
mockConsoleLog = jest.spyOn(global.console, 'log');
mockConsoleLog = jest.spyOn(unsafeConsole, 'log');
const { startES, startKibana } = createTestServers({
adjustTimeout: jest.setTimeout,

View file

@ -15,6 +15,7 @@ import { esTestConfig } from '@kbn/test';
import { firstValueFrom, Subject } from 'rxjs';
import { CliArgs } from '@kbn/config';
import Semver from 'semver';
import { unsafeConsole } from '@kbn/security-hardening';
function nextMinor() {
return Semver.inc(esTestConfig.getVersion(), 'minor') || '10.0.0';
@ -36,7 +37,7 @@ describe('Version Compatibility', () => {
let consoleSpy: jest.SpyInstance;
beforeEach(() => {
consoleSpy = jest.spyOn(console, 'log');
consoleSpy = jest.spyOn(unsafeConsole, 'log');
});
afterEach(async () => {

View file

@ -8,12 +8,13 @@
import { schema } from '@kbn/config-schema';
import { createRoot, request } from '@kbn/core-test-helpers-kbn-server';
import { unsafeConsole } from '@kbn/security-hardening';
describe('request logging', () => {
let mockConsoleLog: jest.SpyInstance;
beforeAll(() => {
mockConsoleLog = jest.spyOn(global.console, 'log');
mockConsoleLog = jest.spyOn(unsafeConsole, 'log');
});
afterEach(() => {

View file

@ -10,6 +10,7 @@ import type { LoggerContextConfigInput } from '@kbn/core-logging-server';
import { createRoot as createkbnTestServerRoot } from '@kbn/core-test-helpers-kbn-server';
import { InternalCoreSetup } from '@kbn/core-lifecycle-server-internal';
import { Subject } from 'rxjs';
import { unsafeConsole } from '@kbn/security-hardening';
function createRoot() {
return createkbnTestServerRoot({
@ -45,7 +46,7 @@ describe('logging service', () => {
let root: ReturnType<typeof createRoot>;
let mockConsoleLog: jest.SpyInstance;
beforeAll(async () => {
mockConsoleLog = jest.spyOn(global.console, 'log');
mockConsoleLog = jest.spyOn(unsafeConsole, 'log');
root = createRoot();
await root.preboot();
@ -148,7 +149,7 @@ describe('logging service', () => {
};
beforeAll(async () => {
mockConsoleLog = jest.spyOn(global.console, 'log');
mockConsoleLog = jest.spyOn(unsafeConsole, 'log');
root = createRoot();
await root.preboot();

View file

@ -7,6 +7,7 @@
*/
import { createRoot as createkbnTestServerRoot } from '@kbn/core-test-helpers-kbn-server';
import { unsafeConsole } from '@kbn/security-hardening';
function createRootWithRoles(roles: string[]) {
return createkbnTestServerRoot({
@ -39,7 +40,7 @@ describe('node service global context', () => {
let mockConsoleLog: jest.SpyInstance;
beforeAll(async () => {
mockConsoleLog = jest.spyOn(global.console, 'log');
mockConsoleLog = jest.spyOn(unsafeConsole, 'log');
root = createRootWithRoles(roles);
await root.preboot();

View file

@ -157,6 +157,7 @@
"@kbn/core-plugins-contracts-server",
"@kbn/dev-utils",
"@kbn/server-http-tools",
"@kbn/security-hardening",
"@kbn/core-base-server-mocks",
],
"exclude": [

View file

@ -14,3 +14,5 @@ require('./dns_ipv4_first');
require('@kbn/babel-register').install();
require('./polyfill');
require('@kbn/security-hardening');

View file

@ -13,6 +13,7 @@
"kbn_references": [
{ "path": "../../tsconfig.json" },
"@kbn/babel-register",
"@kbn/security-hardening",
],
"exclude": [
"target/**/*",

View file

@ -1342,6 +1342,8 @@
"@kbn/searchprofiler-plugin/*": ["x-pack/plugins/searchprofiler/*"],
"@kbn/security-api-integration-helpers": ["x-pack/test/security_api_integration/packages/helpers"],
"@kbn/security-api-integration-helpers/*": ["x-pack/test/security_api_integration/packages/helpers/*"],
"@kbn/security-hardening": ["packages/kbn-security-hardening"],
"@kbn/security-hardening/*": ["packages/kbn-security-hardening/*"],
"@kbn/security-plugin": ["x-pack/plugins/security"],
"@kbn/security-plugin/*": ["x-pack/plugins/security/*"],
"@kbn/security-plugin-types-common": ["x-pack/packages/security/plugin_types_common"],

View file

@ -5748,6 +5748,10 @@
version "0.0.0"
uid ""
"@kbn/security-hardening@link:packages/kbn-security-hardening":
version "0.0.0"
uid ""
"@kbn/security-plugin-types-common@link:x-pack/packages/security/plugin_types_common":
version "0.0.0"
uid ""