Skip to content

Admin Bar customizer stores the saving user's My Account node and shows that user to everyone #4524

Description

@johansolve

Description

Plugin: Neve Pro (neve-pro-addon) 3.2.5 — WP Dashboard Customizer module (Admin Bar). Feature introduced in Neve 4.2.0.

Summary:
When an admin bar layout is saved via the WP Dashboard Customizer (Admin Bar), the "my-account" and "user-info" nodes are stored as a static HTML snapshot of whoever saved the layout. That snapshot is then replayed for every logged-in user, so all users see the saving user's name, username and Gravatar in the top-right admin bar greeting and dropdown — regardless of who is actually logged in.

Scope:
The wrong data is stored in the option "neve_admin_bar_menu" (wp_options), so it persists across environments when the database is cloned (production, staging, local all show the same wrong user). It is not an HTTP/page cache. Resetting the admin bar customizations (delete_option 'neve_admin_bar_menu') fixes it until the layout is saved again, at which point it re-captures the new saving user.

Root cause:
includes/modules/dashboard_customizer/admin/admin_bar.php

On save, the node's full original HTML is stored as "titleDefault" (the live HTML of the my-account / user-info node at the moment the saving user opened the editor). On render (apply_menu_customizations), for "my-account" only the text before the first tag ("Howdy,") is replaced, and for "user-info" only the edit-profile span text is replaced; the rest of the snapshot — the display-name span, the username span and the avatar img — is output verbatim:

  • my-account handling (approx. lines 240-242): new title = preg_replace('/^[^<]*/', label, $original_html) — keeps the saved display-name span.
  • user-info handling (approx. lines 243-256): only the edit-profile span content is replaced — keeps the saved avatar + display name + username.

The personalized nodes (my-account, user-info) are per-user and must never be snapshotted; they should be re-rendered from the current user (wp_get_current_user) at output time, not restored from the saved titleDefault.

Suggested fix:
Exclude "my-account" and "user-info" from the titleDefault snapshot/restore logic, and let WordPress render those nodes live for the current user. Apply only ordering/visibility/label customizations to them, never the cached HTML body.

Environment notes:
Reproduced on production, staging and local (shared cloned DB). Child theme does not touch the admin bar.

Step-by-step reproduction instructions

  1. Log in as user A (display name "User A", login "usera").
  2. Open the WP Dashboard Customizer, Admin Bar section.
  3. Make any change and save (or just save).
  4. Log in as a different user B (display name "User B", login "userb") in another browser/session.
  5. Look at the admin bar top-right.

Expected:
User B sees "Howdy, User B" with their own username and Gravatar.

Actual:
User B sees "Howdy, User A", username "usera", and user A's Gravatar. The greeting, the display name, the username line and the avatar are all user A's. Clicking "Edit Profile" still correctly opens profile.php for user B, confirming the actual session is B — only the rendered admin bar markup is a stored copy of A.

Screenshots, screen recording, code snippet or Help Scout ticket

No response

Environment info

https://pastebin.com/XpvEU47J

Is the issue you are reporting a regression

No

Metadata

Metadata

Labels

bugThis label could be used to identify issues that are caused by a defect in the product.

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions