diff --git a/packages/kbn-securitysolution-exception-list-components/index.ts b/packages/kbn-securitysolution-exception-list-components/index.ts
index 5811612d8a3a4..0e11a4694384d 100644
--- a/packages/kbn-securitysolution-exception-list-components/index.ts
+++ b/packages/kbn-securitysolution-exception-list-components/index.ts
@@ -19,3 +19,4 @@ export * from './src/list_header';
export * from './src/header_menu';
export * from './src/generate_linked_rules_menu_item';
export * from './src/wildcard_with_wrong_operator_callout';
+export * from './src/partial_code_signature_callout';
diff --git a/packages/kbn-securitysolution-exception-list-components/src/partial_code_signature_callout/index.tsx b/packages/kbn-securitysolution-exception-list-components/src/partial_code_signature_callout/index.tsx
new file mode 100644
index 0000000000000..72836fc78fb55
--- /dev/null
+++ b/packages/kbn-securitysolution-exception-list-components/src/partial_code_signature_callout/index.tsx
@@ -0,0 +1,34 @@
+/*
+ * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public
+ * License v3.0 only", or the "Server Side Public License, v 1".
+ */
+
+import React from 'react';
+import { FormattedMessage } from '@kbn/i18n-react';
+import { i18n } from '@kbn/i18n';
+
+import { EuiCallOut } from '@elastic/eui';
+
+export const PartialCodeSignatureCallout = () => {
+ return (
+
+
+
+ );
+};
diff --git a/packages/kbn-securitysolution-list-utils/src/helpers/index.test.ts b/packages/kbn-securitysolution-list-utils/src/helpers/index.test.ts
index 087b27f136591..fffcabbf41575 100644
--- a/packages/kbn-securitysolution-list-utils/src/helpers/index.test.ts
+++ b/packages/kbn-securitysolution-list-utils/src/helpers/index.test.ts
@@ -7,7 +7,12 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/
-import { getMappingConflictsInfo, fieldSupportsMatches, hasWrongOperatorWithWildcard } from '.';
+import {
+ getMappingConflictsInfo,
+ fieldSupportsMatches,
+ hasWrongOperatorWithWildcard,
+ hasPartialCodeSignatureEntry,
+} from '.';
describe('Helpers', () => {
describe('getMappingConflictsInfo', () => {
@@ -261,4 +266,112 @@ describe('Helpers', () => {
).toBeTruthy();
});
});
+
+ describe('hasPartialCodeSignatureEntry', () => {
+ it('returns false if the entry has neither code signature subject name nor trusted field', () => {
+ expect(
+ hasPartialCodeSignatureEntry([
+ {
+ description: '',
+ name: '',
+ type: 'simple',
+ os_types: ['windows'],
+ entries: [{ type: 'match', value: 'asdf', field: 'someField', operator: 'excluded' }],
+ },
+ ])
+ ).toBeFalsy();
+ });
+ it('returns true if the entry has code signature subject name but not trusted field', () => {
+ expect(
+ hasPartialCodeSignatureEntry([
+ {
+ description: '',
+ name: '',
+ type: 'simple',
+ os_types: ['windows'],
+ entries: [
+ {
+ type: 'match',
+ value: 'asdf',
+ field: 'process.code_signature.subject_name',
+ operator: 'excluded',
+ },
+ ],
+ },
+ ])
+ ).toBeTruthy();
+ });
+ it('returns true if the entry has code signature trusted but not the subject name field', () => {
+ expect(
+ hasPartialCodeSignatureEntry([
+ {
+ description: '',
+ name: '',
+ type: 'simple',
+ os_types: ['windows'],
+ entries: [
+ {
+ type: 'match',
+ value: 'asdf',
+ field: 'process.code_signature.trusted',
+ operator: 'excluded',
+ },
+ ],
+ },
+ ])
+ ).toBeTruthy();
+ });
+ it('returns false if the entry has both code signature subject name and trusted field', () => {
+ expect(
+ hasPartialCodeSignatureEntry([
+ {
+ description: '',
+ name: '',
+ type: 'simple',
+ os_types: ['windows'],
+ entries: [
+ {
+ type: 'match',
+ value: 'asdf',
+ field: 'process.code_signature.subject_name',
+ operator: 'excluded',
+ },
+ {
+ type: 'match',
+ value: 'true',
+ field: 'process.code_signature.trusted',
+ operator: 'excluded',
+ },
+ ],
+ },
+ ])
+ ).toBeFalsy();
+ });
+ it('returns false if the entry has both code signature team_id and trusted fields for mac os', () => {
+ expect(
+ hasPartialCodeSignatureEntry([
+ {
+ description: '',
+ name: '',
+ type: 'simple',
+ os_types: ['macos'],
+ entries: [
+ {
+ type: 'match',
+ value: 'asdf',
+ field: 'process.code_signature.team_id',
+ operator: 'excluded',
+ },
+ {
+ type: 'match',
+ value: 'true',
+ field: 'process.code_signature.trusted',
+ operator: 'excluded',
+ },
+ ],
+ },
+ ])
+ ).toBeFalsy();
+ });
+ });
});
diff --git a/packages/kbn-securitysolution-list-utils/src/helpers/index.ts b/packages/kbn-securitysolution-list-utils/src/helpers/index.ts
index a625d694961ab..8031cfba14f2d 100644
--- a/packages/kbn-securitysolution-list-utils/src/helpers/index.ts
+++ b/packages/kbn-securitysolution-list-utils/src/helpers/index.ts
@@ -1052,3 +1052,38 @@ export const hasWrongOperatorWithWildcard = (
}
});
};
+
+/**
+ * Event filters helper where given an exceptions list,
+ * determine if both 'subject_name' and 'trusted' are
+ * included in an entry with 'code_signature'
+ */
+export const hasPartialCodeSignatureEntry = (
+ items: ExceptionsBuilderReturnExceptionItem[]
+): boolean => {
+ const { os_types: os = ['windows'], entries = [] } = items[0] || {};
+ let name = false;
+ let trusted = false;
+
+ for (const e of entries) {
+ if (e.type === 'nested' && e.field === 'process.Ext.code_signature') {
+ const includesNestedName = e.entries.some(
+ (nestedEntry) => nestedEntry.field === 'subject_name'
+ );
+ const includesNestedTrusted = e.entries.some(
+ (nestedEntry) => nestedEntry.field === 'trusted'
+ );
+ if (includesNestedName !== includesNestedTrusted) {
+ return true;
+ }
+ } else if (
+ e.field === 'process.code_signature.subject_name' ||
+ (os.includes('macos') && e.field === 'process.code_signature.team_id')
+ ) {
+ name = true;
+ } else if (e.field === 'process.code_signature.trusted') {
+ trusted = true;
+ }
+ }
+ return name !== trusted;
+};
diff --git a/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/form.tsx b/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/form.tsx
index 173645eae203e..783fda9a806b2 100644
--- a/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/form.tsx
+++ b/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/form.tsx
@@ -30,8 +30,12 @@ import type { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-t
import {
EVENT_FILTERS_OPERATORS,
hasWrongOperatorWithWildcard,
+ hasPartialCodeSignatureEntry,
} from '@kbn/securitysolution-list-utils';
-import { WildCardWithWrongOperatorCallout } from '@kbn/securitysolution-exception-list-components';
+import {
+ WildCardWithWrongOperatorCallout,
+ PartialCodeSignatureCallout,
+} from '@kbn/securitysolution-exception-list-components';
import { OperatingSystem } from '@kbn/securitysolution-utils';
import { getExceptionBuilderComponentLazy } from '@kbn/lists-plugin/public';
@@ -171,6 +175,9 @@ export const EventFiltersForm: React.FC(false);
+
// This value has to be memoized to avoid infinite useEffect loop on useFetchIndex
const indexNames = useMemo(() => [eventsIndexPattern], []);
const [isIndexPatternLoading, { indexPatterns }] = useFetchIndex(
@@ -563,6 +570,7 @@ export const EventFiltersForm: React.FC =
arg.exceptionItems[0] !== undefined
@@ -725,6 +733,7 @@ export const EventFiltersForm: React.FC
{criteriaSection}
{hasWildcardWithWrongOperator && }
+ {hasPartialCodeSignatureWarning && }
{hasDuplicateFields && (
<>