Problem/Motivation
The toolbar subtrees use a hash to determine if access to the subtree should be allowed in ToolbarController::checkSubTreeAccess(). In certain situations the hash does not match, resulting in a JavaScript error and the subtrees not dynamically loading. Temporarily commenting out the hash check from ToolbarController::checkSubTreeAccess() makes the toggles appear again.
The toolbar module relies on _toolbar_get_subtrees_hash function to generate hash based on admin menu subtrees' length. This information is not same when you call it via `hook_toolbar` and via /toolbar/subtrees Ajax route. This difference is due to multiple reasons, few are:
1. If you are on admin pages, subtree uses stable template to generate html while Ajax uses toolbar module template
2. If there is a customization like adding destination to any of the link then hook_toolbar attaches current page url while Ajax attaches /toolbar/subtrees as destination
Steps to reproduce
- Set the admin menu in vertical mode.
- Make sure to have a site with 2 languages.
- Enable the Account administration pages on Language negotiation > Detection and selection.
- Set the default language to something non-english.
- Set an admin language in your user profile other than the default site language (e.g. english).
- Go to a content page in your content language.
- Refresh the cache (I did this from the content page with devel module).
- Navigate to an admin page.
- Observe that the toolbar submenu toggles (blue arrows) are not shown and there is a JavaScript error.
Proposed resolution
The hash is calculated from the rendered subtrees, but if the rendered content changes, the hash no longer matches with the sent one and the access check fails.
Proposed solution is to use $hash = Crypt::hashBase64(serialize(array_keys($subtrees))); instead of $hash = Crypt::hashBase64(serialize($subtrees));. So that the hash is based on structure, rather than content.
Remaining tasks
- Understand the purpose of the hash(?). Is it related to CSRF, MITM, permissions?
- Agree on an alternative hash input.
User interface changes
Hopefully none
API changes
Probably none
Data model changes
Release notes snippet
| Comment | File | Size | Author |
|---|---|---|---|
| #24 | 3130197-fix_subtree_hash_merge-9-13_10.3.x.patch | 1.92 KB | anairamzap |
| #13 | 3402656-fix-subtree-hash.patch | 1.45 KB | zeeshan_khan |
| #9 | 3130197-9.patch | 534 bytes | scottatdrake |
| #3 | 3130197-2.patch | 553 bytes | ash2303 |
Issue fork drupal-3130197
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
ash2303 commentedComment #3
ash2303 commentedComment #4
longwaveComment #9
scottatdrake commentedRerolled patch against 9.4.x
Comment #13
zeeshan_khan commentedThis one fixes the problem for me.
Comment #14
smustgrave commentedWill need test coverage showing the problem.
Issue summary is also incomplete, recommend using the standard issue template
Comment #15
neograph734I have updated the IS and merged it with the content of #3402656: Toolbar causes a Javascript error if the subtrees content changes between page loads.
The patch from #2 and #9 does not appear to work. It makes the issue go away, but when a new module is installed, the menu does not update and the new links don't become visible. So the hash might be too generic(?).
The patch from #13 does not appear to do anything. The toggles are still missing and the error is still shown?
Should we perhaps try hasing the raw menu tree structure or something instead?
Comment #16
neograph734Comment #17
matthiasm11 commentedCombining the patches from #9 to generate the hash and #13 to fix the caching seems to fix the issue.
Disabling a module makes the corresponding menu item disappear, enabling the module again makes it appear again.
No console errors anymore. I've not investigated this any further.
Comment #18
milos.kroulik commentedI can confirm observations made in #17. So I'm going to create a combined patch.
Comment #19
ericdsd commentedHi milos.kroulik, did you create a combine patch for it yet ?
Note i'm still experiencing it on core 10.3.11.
Comment #23
sleitner commentedToolbarAdminMenuTesttest still needs to be updatedComment #24
anairamzapI've created a patch that merges the ones in #9 and #13 based on core 10.3.x
Leaving this as "Needs work" since a test update is still missing
Comment #25
frontmobeThanks @anairamzap, I can confirm that your patch also cleanly applies to Drupal 10.4.3.
Comment #28
carlos romero commentedComment #29
carlos romero commentedHi, I've forked, applied the change to the 10.4.x branch, and submitted the PR.
Best regards.
Comment #30
smustgrave commentedHave not reviewed but changes need to be against 11.x as that’s the development branch
Comment #34
tintoRebased to 11.x
Greetings from the contrib room at Drupal Developer Days 2025 in Leuven, Belgium.
Comment #35
smustgrave commentedHello!
New parameter probably should be typehinted and parameter doc added
Also will most likely need test coverage
Comment #36
sleitner commentedThe MR doesn't fix the problem when installing/uninstalling modules which only add a sub menu item e.g. "User interface translation" for
localemodule.The keys of the array do not change, so the hash does not change either. Maybe the installed modules list should be in in the hash input, too?
Comment #38
quietone commentedThe Toolbar Module was approved for removal in #3476882: [Policy] Move Toolbar module to contrib.
This is Postponed. The status is set according to two policies. The Remove a core extension and move it to a contributed project and the Extensions approved for removal policies.
The deprecation work is in #3484850: [meta] Tasks to deprecate Toolbar module and the removal work in #3488828: [meta] Tasks to remove Toolbar module.
Toolbar will be moved to a contributed project before Drupal 12.0.0 is released.