Skip to content

[Security Solution] Note avatars ignore the user profile image/initials #280901

Description

@orangecola

Describe the bug:

Everywhere notes are displayed in the Security Solution, the author's avatar is rendered from the stored display-name string only, using a plain EuiAvatar. That produces auto-generated initials and an auto-assigned color, and it ignores the avatar the user configured in their Kibana user profile (uploaded image, or custom initials + color).

The same user therefore shows one avatar in Cases, the user menu, and assignee lists (profile avatar) and a different, generated one on notes. In a workspace where several people annotate the same timeline this makes note authorship harder to scan, and it looks inconsistent next to Cases, which already renders profile avatars for comment authors.

Kibana/Elasticsearch Stack version: reproduced on a clean 9.4.4 stack (Docker images, trial license); the same code is on main at 68d2f14 and on the 9.4 branch

Server OS version: any

Browser and Browser OS versions: any

Elastic Endpoint version: n/a

Original install method: official 9.4.4 Docker images (docker.elastic.co), single-node, trial license

Functional Area: Timelines / Notes

Steps to reproduce:

  1. Start a stack with a trial/platinum license (notes + user profile suggestions are Platinum-gated) and log in as two different users.
  2. For each user, set a profile avatar — upload an image, or set custom initials and a color — via User menu → Edit profile → Avatar.
  3. Open a timeline and have each user add a note.
  4. Look at the author avatars in the timeline Notes tab, in the Participants panel, and in the "Created by" column at Security → Manage → Notes (/app/security/administration/notes).
  5. For comparison, open any case and look at the same two users in the comment stream.

Current behavior:

The avatar is generated from the note's updatedBy / createdBy display-name string. The user's configured profile image is never loaded, and their chosen initials/color are not used.

Affected call sites, all passing a bare name to EuiAvatar:

Location File
Notes list (flyout + timeline Notes tab) x-pack/solutions/security/plugins/security_solution/public/notes/components/notes_list.tsx
Note management page, "Created by" column x-pack/solutions/security/plugins/security_solution/public/notes/pages/note_management_page.tsx
Timeline participants x-pack/solutions/security/plugins/security_solution/public/timelines/components/notes/participants.tsx
Note previews (open timeline) x-pack/solutions/security/plugins/security_solution/public/timelines/components/open_timeline/note_previews/index.tsx
Timeline description comment x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/notes/index.tsx

Expected behavior:

Note avatars should render the author's user profile avatar — image if one is set, otherwise the profile's initials and color — consistent with how Cases renders comment authors. When no matching profile exists (deleted user, note imported from another cluster, unauthenticated writes), fall back to the current generated initials avatar.

Root cause:

Notes do not persist a user profile identifier. Server-side, saved_object.ts stores only a display string:

// x-pack/solutions/security/plugins/security_solution/server/lib/timeline/saved_object/notes/saved_object.ts
savedNote.createdBy = userInfo ? getUserDisplayName(userInfo) : UNAUTHENTICATED_USER;
savedNote.updatedBy = userInfo ? getUserDisplayName(userInfo) : UNAUTHENTICATED_USER;

getUserDisplayName resolves to full_name || email || username. Since the note carries no profile uid, the client has nothing to look the profile up by, and every render site fell back to <EuiAvatar name={...} />.

Worth noting that on the note management page the profile data is already in handnote_management_page.tsx:131 calls useSuggestUsers({ searchTerm: '', enabled: isPlatinumPlus }) to populate the "Created by" filter — it is simply not used when rendering the avatar in the column next to it.

Proposed fix:

Add a shared NoteAvatar component that resolves the display name back to a user profile and renders UserAvatar from @kbn/user-profile-components, falling back to EuiAvatar when no profile matches. It reuses the existing useSuggestUsers hook (already used elsewhere in the Security Solution, cached with staleTime: Infinity), matching on getUserDisplayName(user) === displayName. All five call sites above switch to it.

Known limitation of that approach — verified, and it matters:

useSuggestUsers({ searchTerm: '' }) hits GET /internal/detection_engine/users/_find, which calls security.userProfiles.suggest() without a size. That defaults to DEFAULT_SUGGESTIONS_COUNT = 10 (x-pack/platform/plugins/shared/security/server/user_profile/user_profile_service.ts:44), so the component can only ever see 10 profiles.

Measured on the 9.4.4 repro stack:

Activated user profiles Profiles returned by suggestUsers('') Notes that resolve to a profile avatar
2 2 3 / 3
16 10 1 / 3

With 16 users, Sarah Chen — author of 2 of the 3 notes — was not in the 10 returned profiles, so her notes still render the generated fallback avatar. The name-matching approach therefore only holds on very small deployments, and which users it fixes is effectively arbitrary (the suggest ordering is not stable or authorship-aware).

Two further problems with matching on display name: users sharing a display name are indistinguishable, and the note stores whatever getUserDisplayName returned at write time, so a later change to a user's full_name silently breaks the match for their existing notes.

The durable fix is to persist the author's profile uid on the note saved object and resolve it with bulkGetUserProfiles, keeping name matching only as a fallback for notes written before that change. If we want the display-name approach as a stopgap, it should at least pass an explicit size up to MAX_SUGGESTIONS_COUNT = 100 — but that only moves the cliff from 10 users to 100.

Errors in browser console (if relevant): none

Screenshots (if relevant):

Image Image Image Image
  1. Notes management page — "Created by" shows generated letter avatars (SC, SC, E), not the profile images both users have configured.
  2. Same frame, user menu open — the user menu renders elastic's actual uploaded profile image while the table below shows E for that same user.
  3. Timeline → Notes tab — the notes list, the "Created by" panel and the "Participants" panel all show letter avatars (three of the five affected call sites in one view).
  4. Cases, same two users — Cases renders both users' real profile images in the comment stream, activity log and Participants sidebar. This is the behavior notes should match.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions