Make WordPress Core

Opened 7 weeks ago

Closed 5 weeks ago

Last modified 5 weeks ago

#65121 closed defect (bug) (fixed)

Command Palette: Label can be incorrect for sites served over a CDN

Reported by: peterwilsoncc's profile peterwilsoncc Owned by: peterwilsoncc's profile peterwilsoncc
Milestone: 7.0 Priority: normal
Severity: normal Version: 7.0
Component: Toolbar Keywords: has-patch fixed-major commit dev-reviewed
Focuses: Cc:

Description

The Command Pallet shortcut displayed in the admin bar is incorrect for macOs users when their site is hosted behind a CDN that removes the User-Agent HTTP header from requests passed through to the application server.

This is a relatively common on CDNs as a way to increase cache hits at the edge.

As Control+K does not trigger the command pallete on macOS, this can lead to confusion for users on such a configuration.

Upstream Report: GB#77636

Recommended Fix

Recheck the User-Agent via JavaScript using navigator.userAgent and update the string used in the admin bar if it's determined to be macOS.

Reproduction Steps

  1. Buy a macOS computer/use BrowserStack on macOS.
  2. In your wp-config.php file, add the code $_SERVER['HTTP_USER_AGENT'] = ''; to emulate a site behind a CDN stripping the header
  3. Visit /wp-admin
  4. Observe the shortcut displayed is incorrect
  5. Remove the code added to your wp-config.php file to avoid confusion later.

See upstream issue for screenshot.

Change History (24)

This ticket was mentioned in PR #11636 on WordPress/wordpress-develop by @peterwilsoncc.


7 weeks ago
#1

  • Keywords has-patch added

Adds a JavaScript check of the User-Agent for displaying the text in the admin bar.

On sites served over a CDN is it relatively common for the CDN to strip the User-Agent HTTP header, on macOS systems this causes the incorrect label to be displayed.

See https://github.com/WordPress/gutenberg/issues/77636
Closes Core-65121

## Testing Instructions

  1. Buy a macOS computer/use BrowserStack on macOS.
  2. In your wp-config.php file, add the code $_SERVER['HTTP_USER_AGENT'] = ''; to emulate a site behind a CDN stripping the header
  3. Visit /wp-admin
  4. Ensure the label is correct on this branch.
  5. Ensure the label is incorrect on trunk
  6. Remove the code added to the wp-config file to avoid confusion later.

Trac ticket: https://core.trac.wordpress.org/ticket/65121

## Use of AI Tools

N/A

#3 in reply to: ↑ 2 ; follow-up: @peterwilsoncc
7 weeks ago

Replying to westonruter:

For previous discussions on using JS, see...

Thanks for pointing those out.

The prompt for this ticket was that I noticed my site was displaying Ctrl+K despite using a Mac because I run my overengineered site behind CloudFront.

Do you think that the use of both PHP and JS detection mitigates the concerns of a flash of incorrect rendering by treating the JS test as a last resort in case the PHP detection is incorrect? cc @wildworks

@mukesh27 commented on PR #11636:


7 weeks ago
#4

  1. Buy a macOS computer

😃

#5 in reply to: ↑ 3 @westonruter
7 weeks ago

Replying to peterwilsoncc:

Do you think that the use of both PHP and JS detection mitigates the concerns of a flash of incorrect rendering by treating the JS test as a last resort in case the PHP detection is incorrect? cc @wildworks

I had forgotten that JS was not being used to render the node actually. I had assumed it was because there seems to be an issue with the admin bar flickering with view transitions: https://core.trac.wordpress.org/ticket/65032#comment:8

But ultimately it does have hide-if-no-js which requires JS to run before the node is revealed. But this JS runs in head before rendering, as I recall, so that is okay. We should just make sure this new inline script also runs in the head.

cc @zieladam

#6 @sabernhardt
7 weeks ago

  • Component changed from Administration to Toolbar

#7 @peterwilsoncc
7 weeks ago

As best I can tell there are two options for running the JavaScript fallback ASAP:

  • Add the script in $wp_admin_bar->add_node( meta.html ) -- soonest
  • Add a wp_print_inline_script_tag() call to the wp_after_admin_bar_render action -- very soon after render

In both cases, this would add a blocking script to the HTML header.

The JavaScript fallback will be required by a small number of users: Mac OS users running their sites over CDNs that strip the User Agent header for admin requests.

I'm inclined to accept the risk of a flash of incorrect content for those users and reconsider in 7.0.1 depending on the number of support requests/bug reports. It seems better than adding a blocking script the the HTML header for an edge case.

#8 @westonruter
7 weeks ago

Since the blocking script is inline, then there is no external HTTP request that is contributing to it the blocking. There are already a few inline scripts in the HEAD in addition to external blocking scripts, so I don't think adding a new inline script will have any measurable impact on performance.

I think your $wp_admin_bar->add_node( meta.html ) solution is the best.

@peterwilsoncc commented on PR #11636:


7 weeks ago
#9

@westonruter I've rewritten this based on the discussion on the ticket. I've also switched to navigator.platform for increased reliability over the UA sniffing.

@peterwilsoncc commented on PR #11636:


7 weeks ago
#10

@westonruter Thanks for the approval. I'm inclined to remain with navigator.platform as, while uncommon, UA is editable user input whereas the platform is not.

@westonruter commented on PR #11636:


7 weeks ago
#11

UA is editable user input whereas the platform is not.

Wouldn't this be a feature then? In De tools, someone might want to emulate a Mac to see what the shortcut looks like on that environment. How else would an editable user agent be problematic?

@peterwilsoncc commented on PR #11636:


7 weeks ago
#12

I'm of the view we write code for users rather than developers. The most reliable way of testing UA issues is to use BrowserStack or similar.

@peterwilsoncc commented on PR #11636:


7 weeks ago
#13

As both of our opinions are loosely held, I did a coin toss and have switch over to user agent using the diff in https://github.com/WordPress/wordpress-develop/pull/11636#pullrequestreview-4178279806

https://github.com/user-attachments/assets/ee9d1e99-787d-4f0e-9b0e-a18f16d3e7b8

#14 @peterwilsoncc
7 weeks ago

  • Resolution set to fixed
  • Status changed from assigned to closed

In 62282:

Toolbar: Add JavaScript fallback for determining command palette icon.

Introduces a JavaScript fallback for determining whether the command palette icon in the toolbar should display ⌘Kfor Apple devices.

This is to account for sites behind a CDN as it's common for the User-Agent header to be stripped from the request sent to the application server in order to increase cache hits on the edge.

Props peterwilsoncc, westonruter, mukesh27, ramonopoly.
Fixes #65121.

#15 @peterwilsoncc
7 weeks ago

  • Keywords dev-feedback added
  • Resolution fixed deleted
  • Status changed from closed to reopened

Reopening for merging [62282] to the 7.0 branch pending another committer's sign off.

This ticket was mentioned in PR #11735 on WordPress/wordpress-develop by @desrosj.


5 weeks ago
#16

Follow up to r62282.

  • Adds the case-insensitive flag to the matching JavaScript Regex.
  • Guards against a TypeError if the admin bar element has been moved or manipulated in some way.

Trac ticket: #65121.

## Use of AI Tools

AI assistance: Yes
Tool(s): Claude
Model(s): Opus 4.7
Used for: Used Claude to analyze the previous changeset to try and find potential issues. Validated them before fixing here in the PR.

#17 @desrosj
5 weeks ago

I ran this through Claude and it pointed out a few things that I've confirmed and tested.

  • I noticed that the PHP-based Regex has /i but the JavaScript pattern does not. Is this intentional? If not, we should probably also be case insensitive in the JavaScript.
  • It seems that it's possible to encounter a TypeError if a plugin or theme manipulates the admin bar and querySelector is unable to find the element.

I've created a PR with both of these fixes.

A few other things Claude noted that aren't blockers (in my opinion):

  • navigator.userAgent is being deprecated in favor of navigator.userAgentData. Not an issue today, but possibly in the future.
  • The pattern does not cover older iPads. While newer iPads report desktop-like UA values, older ones use iPad.

#18 @westonruter
5 weeks ago

@desrosj PR approved, though not sure about the changes to .github.

Regarding navigator.userAgentData, this is not supported by Safari or Firefox: https://caniuse.com/mdn-api_navigator_useragentdata

I don't think it is actually deprecated. At least, it is not noted as such in MDN: https://developer.mozilla.org/en-US/docs/Web/API/Navigator/userAgent

I think the desire was to deprecate it to try to move away from fingerprinting, but and this seems to have been short-lived and it seems it is not discouraged: https://stackoverflow.com/a/43754322

This was also discussed on the merged PR (in a resolved comment): https://github.com/WordPress/wordpress-develop/pull/11636#discussion_r3144372264

@desrosj commented on PR #11735:


5 weeks ago
#19

Thanks @westonruter. I maintain a dependabot.yml file in the trunk branch of my fork. I usually create a new branch from upstream/trunk for a PR, but accidentally branched from my trunk branch and included the dependabot.yml file.

I've rebased and removed.

#20 @desrosj
5 weeks ago

  • Resolution set to fixed
  • Status changed from reopened to closed

In 62320:

Toolbar: Improvements to changes in [62282].

This updates the JavaScript based regular expression to be case-insensitive, which matches the corresponding PHP pattern.

A defensive check has alos been added to avoid a TypeError if the admin bar is manipulated in a way that changes the path of the targeted element.

Follow up to [62282].

Props westonruter.
Fixes #65121.

#21 @desrosj
5 weeks ago

  • Keywords fixed-major commit dev-reviewed added; dev-feedback removed
  • Resolution fixed deleted
  • Status changed from closed to reopened

Reopening to backport both [62282] and [62320].

#22 @jorbin
5 weeks ago

[62282] and [62320] look good for backport to the 7.0 branch.

#23 @desrosj
5 weeks ago

  • Resolution set to fixed
  • Status changed from reopened to closed

In 62322:

Toolbar: Add JavaScript fallback for determining command palette icon.

Introduces a JavaScript fallback for determining whether the command palette icon in the toolbar should display ⌘Kfor Apple devices.

This is to account for sites behind a CDN as it's common for the User-Agent header to be stripped from the request sent to the application server in order to increase cache hits on the edge.

Reviewed by westonruter, desrosj.
Merges [62282] to the 7.0 branch.

Props peterwilsoncc, westonruter, mukesh27, ramonopoly, desrosj.
Fixes #65121.

#24 @desrosj
5 weeks ago

In 62323:

Toolbar: Improvements to changes in [62282].

This updates the JavaScript based regular expression to be case-insensitive, which matches the corresponding PHP pattern.

A defensive check has alos been added to avoid a TypeError if the admin bar is manipulated in a way that changes the path of the targeted element.

Follow up to [62282].

Reviewed by westonruter, desrosj, jorbin.
Merges [62320] to the 7.0 branch.

Props westonruter, dersosj, jorbin.
Fixes #65121.

Note: See TracTickets for help on using tickets.