Skip to content

Commit 9aa9756

Browse files
Security Solution] Fix string spread bug when syncing watchlists to Entity Store (#260941)
### Summary: Fix string spread bug when syncing watchlists to entity store Fixes a bug where single-string `entity.attributes.watchlists` values in the Entity Store were being incorrectly parsed and spread into an array of individual characters during sync. If the Entity Store contained a single string value instead of an array (e.g., `"privileged-user-monitoring-watchlist-id"`), the sync logic would destructure it via `[...watchlists, watchlistId]`, resulting in an array of characters `["p", "r", "i", "v", ...]`. This commit adds defensive checks in both `WatchlistEntitiesService` (when reading from Elasticsearch) and `entity_store_sync` (before mutating) to ensure `currentWatchlists` is always safely coerced into an array of strings before any spread operations occur. --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
1 parent d0020e7 commit 9aa9756

File tree

2 files changed

+16
-5
lines changed

2 files changed

+16
-5
lines changed

x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/watchlists/entities/service.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,15 @@ export const createWatchlistEntitiesService = ({
101101

102102
acc.entityIdsByType[entityType].push(euid);
103103

104-
const watchlists = get(record, 'entity.attributes.watchlists') as string[] | undefined;
104+
const rawWatchlists = get(record, 'entity.attributes.watchlists');
105+
const watchlists = Array.isArray(rawWatchlists)
106+
? rawWatchlists
107+
: typeof rawWatchlists === 'string'
108+
? [rawWatchlists]
109+
: undefined;
110+
105111
if (watchlists) {
106-
acc.watchlistsByEuid.set(euid, watchlists);
112+
acc.watchlistsByEuid.set(euid, watchlists as string[]);
107113
}
108114

109115
if (!isIndexSync) {

x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/watchlists/entity_sources/sync/entity_store_sync.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,11 @@ export const addWatchlistAttributeToStore = async ({
3434
if (entityRefs.length === 0) return;
3535

3636
const objects = entityRefs.map(({ euid, type, currentWatchlists }) => {
37-
const watchlists = currentWatchlists ?? [];
37+
const watchlists = Array.isArray(currentWatchlists)
38+
? currentWatchlists
39+
: typeof currentWatchlists === 'string'
40+
? [currentWatchlists]
41+
: [];
3842
const updated = watchlists.includes(watchlistId) ? watchlists : [...watchlists, watchlistId];
3943

4044
return {
@@ -72,8 +76,9 @@ export const removeWatchlistAttributeFromStore = async ({
7276
watchlistId: string;
7377
}): Promise<void> => {
7478
// Only update entities whose current watchlists are known — if we don't have the current value we'd blindly write an empty array to the store.
75-
const knownRefs = entityRefs.filter((ref): ref is EntityRef & { currentWatchlists: string[] } =>
76-
Boolean(ref.currentWatchlists)
79+
const knownRefs = entityRefs.filter(
80+
(ref): ref is EntityRef & { currentWatchlists: string[] } =>
81+
Boolean(ref.currentWatchlists) && Array.isArray(ref.currentWatchlists)
7782
);
7883
if (knownRefs.length === 0) return;
7984

0 commit comments

Comments
 (0)