Problem/Motivation

RestMenuItemsResource::getElementValue() calls $url->toString(TRUE)->getGeneratedUrl() in four places, discarding the GeneratedUrl wrapper that carries bubbleable cacheability metadata.

When a menu item targets a CSRF-protected route (notably user.logout), the URL's cache metadata is lost. REST menu responses are cached without it, leading to cross-user leakage of session-specific tokens for same-role users.

Steps to reproduce

  1. Fresh Drupal 11.x install with rest_menu_items 3.0.x and the core rest module enabled.
  2. At /admin/config/services/rest, enable the rest_menu_item resource for GET with json format and
    cookie authentication.
  3. Grant access GET on Menu items per menu resource to any authenticated role.
  4. Create two users (User A, User B) and assign both the same authenticated role — the default authenticated role is enough, since the
    account menu already exposes user.logout to all authenticated users.
  5. In one browser session, log in as User A. Request GET /api/menu_items/account. In the JSON response, note the relative field of the
    entry whose key is user.logout — it contains ?token=<TOKEN_A>.
  6. In a separate browser session (or curl with a different cookie jar), log in as User B. Request GET /api/menu_items/account.
  7. Compare the ?token=... value in both responses.

Expected: tokens differ — each user has their own session-specific token.

Actual: tokens are identical. User B's response is the cached copy of User A's. Response headers confirm: x-drupal-dynamic-cache: HIT
on User B's request, and x-drupal-cache-contexts lists user.permissions only — no session.

Proposed resolution

Capture the GeneratedUrl wrapper at each call site and merge its bubbleable cacheability into a per-request accumulator; attach the accumulator to the response in get().

Remaining tasks

User interface changes

API changes

Data model changes

Command icon 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

petar_basic created an issue. See original summary.

petar_basic’s picture

Assigned: petar_basic » Unassigned
Status: Active » Needs review
StatusFileSize
new4 KB

MR + patch attached. Captures the GeneratedUrl returned by each ->toString(TRUE) call site and merges its bubbleable cacheability onto the response.

End-to-end fix also needs core issue https://www.drupal.org/project/drupal/issues/3587298 — verified both together in a two-user reproduction on a vanilla install.

petar_basic’s picture

Patch against 3.0.5

fago’s picture

Status: Needs review » Reviewed & tested by the community

I reviewed the fix along-side with the core fix. Fix makes sense and works as it should, MR is good also, we should make sure this metadata is preserved.

I've tested it to work correctly also, all ready!

  • 4f70e235 committed on 3.0.x
    fix: #3587299: Propagate URL bubbleable cacheability metadata to the...
batigolix’s picture

Status: Reviewed & tested by the community » Fixed

Thanks for helping out

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.