Problem/Motivation

In #3452426: Insufficient cacheability information bubbled up by UserAccessControlHandler we fixed the fact that UserAccessControlHandler set the wrong cacheable metadata. A consequence of this is that, if something checks for 'view' access on a user when you do not have the "access user profiles" permission, we need to add the user cache context because of the "is it your own profile" check.

UserThemeHooks::preprocessUsername() uses this access check to determine whether to display the username as a link to the user profile. However, the access check's cacheable metadata is not captured or bubbled from the preprocess method, which can result in a user viewing another user's username (for example, as a node's author) as being linked to the viewed user's profile despite the viewing user not having access to view the profile.

However, capturing cacheable metadata correctly from UserThemeHooks::preprocessUsername() would result in the user cache context from the viewaccess check bubbling and negatively affecting cacheability in the render cache and dynamic page cache. This can be addressed here as well by creating a new entity operation that skips the "is it your own profile" check and showing a link/no link based solely on whether user have the access user profiles permission.

Steps to reproduce

  1. Install Drupal with Standard profile (drush si standard -y)
  2. Create two users (e.g. test1, test2) with the Content editor role
  3. Log in as one of the content editors (test1)
  4. Create a new Article node and save
  5. Observe when viewing the new Article node that the author name ("By test1") is linked to the author's (test1) profile
  6. Click the author link and confirm the profile is viewable
  7. Log out
  8. Log in as the other content editor (test2)
  9. View the Article node created by the other Content editor
  10. Observe when viewing the new Article node that the author name ("By test1") is linked to the author's (test1) profile
  11. Click the author link and confirm the profile page shows access denied

Proposed resolution

  • Capture the cache metadata from access checks used in template_preprocess_username() and make sure it is applied to render array and bubbled when rendered
  • Add entity operation 'view linked label' specifically to check access for whether all users can link to a user profile (for the use of links to authors of entities). This varies from the 'view' operation for user entities in that there is no exception for users viewing their own profiles. This is to prevent the user cache context from being bubbled

Apply a short-term fix while we try to move template_preprocess_node() to view displays. (see below under remaining tasks)

Remaining tasks

  1. Fix the bug in the short term, preferably by making template_preprocess_node properly use the entity reference label formatter, see: https://www.drupal.org/node/2726125
  2. In the long term, we need to gut or get rid of template_preprocess_node() in favor of #2353867: [META] Expose Title and other base fields in Manage Display

User interface changes

N/A

Introduced terminology

N/A

API changes

TBD

Data model changes

N/A

Release notes snippet

Issue fork drupal-3506444

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

kristiaanvandeneynde created an issue. See original summary.

kristiaanvandeneynde’s picture

Relevant code:

// UserAccessControlHandler::checkAccess() snippet
 case 'view':
        // Only allow view access if the account is active.
        $result = AccessResult::allowedIfHasPermission($account, 'access user profiles');

        if ($result->isAllowed()) {
          // Does not run if you do not have the permission.
        }

        // Users can view own profiles at all times.
        return $result->orIf(AccessResult::allowedIf($account->id() == $entity->id())->addCacheContexts(['user']));
// node.module template_preprocess_node()
  $skip_custom_preprocessing = $node->getEntityType()->get('enable_base_field_custom_preprocess_skipping');
  $submitted_configurable = $node->getFieldDefinition('created')->isDisplayConfigurable('view') || $node->getFieldDefinition('uid')->isDisplayConfigurable('view');

  if (!$skip_custom_preprocessing || !$submitted_configurable) {
    $variables['date'] = \Drupal::service('renderer')->render($variables['elements']['created']);
    unset($variables['elements']['created']);
    $variables['author_name'] = \Drupal::service('renderer')->render($variables['elements']['uid']); // THIS TRIGGERS USER ACCESS CHECK.
    unset($variables['elements']['uid']);
  }
catch’s picture

A label-specific permissions seems like a good idea.

Linking an old issue.

kristiaanvandeneynde’s picture

Crediting my colleague Anna as she found this bug and managed to narrow it down to node.module. I took over from there.

kristiaanvandeneynde’s picture

catch’s picture

https://www.drupal.org/node/2726125 if we used the entity reference label formatter, or equivalent logic, then we'd not be doing these permissions checks at all.

kristiaanvandeneynde’s picture

Issue summary: View changes
kristiaanvandeneynde’s picture

Issue summary: View changes

kristiaanvandeneynde’s picture

Status: Active » Needs review

Posted a proof-of-concept that I can confirm on our projects skips the user 'view' access check and trades it in for a 'view label' access check.

godotislate’s picture

Status: Needs review » Needs work

I'm not able to reproduce this issue on HEAD with standard profile install:

Steps taken:

  • Install Drupal core with standard profile
  • Uninstall page_cache module
  • Set system.performance cache.page.max to 86400 (Browser and proxy cache maximum age 1 day)
  • Confirm no roles besides administrator have "View user information" (access user profiles) permission
  • Log in as admin and create an Article node and save
  • View the node as anonymous
  • Observe Cache-Control header is "max-age=86400, public" and X-Drupal-Dynamic-Cache is "MISS"
  • Reload and observe X-Drupal-Dynamic-Cache is "HIT"
  • As admin, Add a comment to the node
  • Reload node page as anon and X-Drupal-Dynamic-Cache is "MISS"
  • Reload node page as anon and X-Drupal-Dynamic-Cache is "HIT"

Additionally, in this line in template_preprocess_node():
$variables['author_name'] = \Drupal::service('renderer')->render($variables['elements']['uid']);
$variables['elements']['uid'] contains a render array with the uid field using the "author" formatter (Drupal\user\Plugin\Field\FieldFormatter\AuthorFormatter), which uses the same "view label" entity access check as the label formatter.

berdir’s picture

Didn't try to reproduce yet, but I can't imagine that we don't have test coverage for this, between dynamic page cache tests, performance tests and so on.

catch’s picture

Status: Needs work » Postponed (maintainer needs more info)

I think this is needs more info. The umami node page performance tests should include dynamic page cache hits on a node, not sure if they have the right permissions, and because they're real browser tests they can't check headers so it would be more checking the dynamic page cache hit.

I do think we should try to gut node preprocess though either way.

kristiaanvandeneynde’s picture

Hmm, this is awkward. We have the same symptoms on two different projects and the MR fixes it. We do use a sort of base profile of our own so let me see if that or any of the modules it ships with interferes with $variables['elements']['uid'] in any way. Have a full day scheduled for this tomorrow so will see what I can find.

kristiaanvandeneynde’s picture

Status: Postponed (maintainer needs more info) » Needs review

I can confirm that on a vanilla install it does get called, but the result is discarded. From user.module template_preprocess_username():

  if ($account instanceof AccessibleInterface) {
    $variables['profile_access'] = $account->access('view');
  }

As you can see, the access check's cacheable netadata is not used at all. Isn't that a bug on its own? You'd think that whatever cacheable metadata determines user view access needs to be added to the page.

I also confirmed that $variables['elements']['uid'] is the same on a vanilla install and our installs.

Still digging why on our sites it does bubble up (or perhaps comes from somewhere else). The rabbit hole goes deeper.

kristiaanvandeneynde’s picture

Status: Needs review » Postponed (maintainer needs more info)
catch’s picture

Had a quick look at user_preprocess_user() and was horrified. Opened #3506680: Remove anonymous commenter support from user module for a start.

On the view profile stuff, I think we might need a 'view linked label' entity access operation, which does everything except the own account check, and then 'view' also includes the own account check or something like that. We should not be linking to people's own profiles in node submitted information when they otherwise wouldn't get a link for anyone else, that's just weird.

kristiaanvandeneynde’s picture

Priority: Critical » Major
Status: Postponed (maintainer needs more info) » Active

Okay so I'm going to be more careful with my statements now because I resent that I cried wolf and it wasn't reproducible on a clean install. I do hope you understand I felt compelled to create a critical issue given the impact if my findings were true.

The bug we found on one project was due to the markerio module adding the user cache context to every single page. See #3506671: Replace using user cache context by lazy loaders to avoid killing the Dynamic Page Cache

The reason I came across core first, was due to how I was debugging. I put XDebug listeners on the Renderer and RefinableCacheableDependencyTrait to track down where the user cache context was being added. This led to me seeing a lot of user cache contexts being merged in (one for every node on the page) and that never happened before. Only after the UserAccessControlHandler fix mentioned in the IS does this happen.

Now, because we are needlessly rendering user names and user names can link to a profile if you have access to it, we basically run a user 'view' access check on every page with a node on it. This leads to the user cache context being added to something that luckily never gets used. But that still feels really dirty.

The bug is very much alive in core, because by all means should that access check actually bubble up. So the only thing saving us here from an uncacheable website is the fact that template_preprocess_username() does a poor job at consuming the cacheable metadata of an access check it ran.

Damn...

Marking as major because of the access checks not bubbling up, but it's no longer critical as one bug cancels out the other. Just not sure how we should proceed here. Feels like a lot of work to rephrase this issue to be about the access bug in template_preprocess_username() so maybe we should open a follow-up but mark it as "please don't fix yet or all hell will break loose" and postpone it until we no longer needlessly render usernames all over.

Also keep in mind that if we fix the access check bubbling up, any page that has author names with links enabled will start varying by user, killing caching once more. So perhaps we need to rethink whether we want to keep that "can access own profile" logic.

Either way, will debug our 2nd project with the same symptoms now. Could very well also be markerio running havoc there.

kristiaanvandeneynde’s picture

On the view profile stuff, I think we might need a 'view linked label' entity access operation, which does everything except the own account check, and then 'view' also includes the own account check or something like that. We should not be linking to people's own profiles in node submitted information when they otherwise wouldn't get a link for anyone else, that's just weird.

This would also be an acceptable fix. But what would we render in that case when you do not have access to view profiles? A label that links to an account but gives a 403 as you click on it?

catch’s picture

StatusFileSize
new33.16 KB

But what would we render in that case when you do not have access to view profiles? A label that links to an account but gives a 403 as you click on it?

If you don't have access to view profiles, you get a label that doesn't link, just the display name for the user. Uploading a screenshot from my 11.x sandbox logged out.

I think that the current logic in HEAD means that you would see this for every user, except for yourself - and to me that is a user facing bug as well as a caching issue because there is just no reason to render this differently for the current user - you can get to your own profile from the user menu etc.

If we're eating the cache contexts, then what probably happens is that most of the time, the username doesn't get linked, because someone else views the article first before it gets in render cache, but very occasionally, it does get linked for the current user, and then it would be incorrectly cached as a link, leading to a 403. Didn't try to reproduce this though.

catch’s picture

Title: Any page with a node on it is completely uncacheable if you do not have the "access user profiles" permission » template_preprocess_user() doesn't handle cacheability correctly
kristiaanvandeneynde’s picture

By the way, doesn't the needless rendering of usernames mean that we tag said pages with the 'user:ID' cache tag? So if you have an expensive page with 20 nodes on it from different authors and one of them updates their account, your expensive page gets invalidated? Even if you never showed any of their names to begin with?

kristiaanvandeneynde’s picture

Issue summary: View changes
kristiaanvandeneynde’s picture

Issue summary: View changes
catch’s picture

I didn't check if we're throwing away the cache tags too or not, but yes if we're not that would happen. And if we're throwing away the cache tags then unless something else adds the user as a cacheable dependency then content won't reflect changes to the username.

godotislate’s picture

By the way, doesn't the needless rendering of usernames mean that we tag said pages with the 'user:ID' cache tag?

Just checked, and when I comment out this line in template_preprocess_node():

$variables['author_name'] = \Drupal::service('renderer')->render($variables['elements']['uid'])

The user:ID tag is not in the X-Drupal-Cache-Tags header.

When I restore the line, user:ID is in the header.

godotislate’s picture

Title: template_preprocess_user() doesn't handle cacheability correctly » template_preprocess_username() doesn't handle cacheability correctly

I can confirm that on a vanilla install it does get called, but the result is discarded. From user.module template_preprocess_username():

  if ($account instanceof AccessibleInterface) {
    $variables['profile_access'] = $account->access('view');
  }

I just looked at template_preprocess_username() and as mentioned there is no capturing of cache metadata at all. In the part mentioned above:

  if ($account instanceof AccessibleInterface) {
    $variables['profile_access'] = $account->access('view');
  }
  else {
    $variables['profile_access'] = \Drupal::currentUser()->hasPermission('access user profiles');
  }

In either condition, the value returned and set to $variables['profile_access'] is a boolean, and not an access object, so there is no cache metadata.

As an experiment, I tested this change:

diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index a22c79094da..2d2e681a81f 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -138,7 +138,11 @@ function user_preprocess_block(&$variables): void {
  *   - account: The user account (\Drupal\Core\Session\AccountInterface).
  */
 function template_preprocess_username(&$variables): void {
+  $metadata = \Drupal\Core\Render\BubbleableMetadata::createFromRenderArray($variables);
   $account = $variables['account'] ?: new AnonymousUserSession();
+  if ($account instanceof \Drupal\Core\Cache\CacheableDependencyInterface) {
+    $metadata->addCacheableDependency($account);
+  }

   $variables['extra'] = '';
   $variables['uid'] = $account->id();
@@ -164,11 +168,13 @@ function template_preprocess_username(&$variables): void {
   }
   $variables['name'] = $name;
   if ($account instanceof AccessibleInterface) {
-    $variables['profile_access'] = $account->access('view');
+    $profile_access = $account->access('view', NULL, TRUE);
   }
   else {
-    $variables['profile_access'] = \Drupal::currentUser()->hasPermission('access user profiles');
+    $profile_access = \Drupal\Core\Access\AccessResultAllowed::allowedIfHasPermission(\Drupal::currentUser(), 'access user profiles');
   }
+  $metadata->addCacheableDependency($profile_access);
+  $variables['profile_access'] = $profile_access->isAllowed();

   $external = FALSE;
   // Populate link path and attributes if appropriate.
@@ -198,6 +204,7 @@ function template_preprocess_username(&$variables): void {
       ])->toString();
     }
   }
+  $metadata->applyTo($variables);
 }

 /**

Now when viewing the node, I do see the x-drupal-dynamic-cache header as "UNCACHEABLE (poor cacheability)" as well as "user" in x-drupal-cache-contexts.

I also updated this issue's title from template_preprocess_user() to template_preprocess_username(), but please correct if this is a mistake.

kristiaanvandeneynde’s picture

Thanks for the confirmations @godotislate!

Keep in mind that if we fix user.module here before we fix node.module in another issue, we actually will introduce the critical issue I reported in the first place.

godotislate’s picture

On the view profile stuff, I think we might need a 'view linked label' entity access operation, which does everything except the own account check,

Keep in mind that if we fix user.module here before we fix node.module in another issue, we actually will introduce the critical issue I reported in the first place.

I think the fix might be easier than expected, and doesn't need a new entity access operation.

Changing this in template_preprocess_username():

  if ($account instanceof AccessibleInterface) {
    $variables['profile_access'] = $account->access('view');
  }
  else {
    $variables['profile_access'] = \Drupal::currentUser()->hasPermission('access user profiles');
  }

to

  $variables['profile_access'] = FALSE;
  if ($account instanceof UserInterface) {
    $profile_access = AccessResultAllowed::allowedIfHasPermission(\Drupal::currentUser(), 'access user profiles');
    $metadata->addCacheableDependency($profile_access);
    $variables['profile_access'] = $profile_access->isAllowed();
  }

should hopefully do all that's needed.

catch’s picture

I think hard-coding the permission is fine in this case so #31 looks good to me.

godotislate’s picture

Status: Active » Needs review

I was wrong about hard-coding the permission. For the "view" operation in UserAccessControlHandler::checkAccess(), there are also checks whether the user being viewed is active. Adding the new 'view linked label' operation is relatively low lift anyway, so pushed up MR 11216.

The IS needs an update, which I can get to later.

kristiaanvandeneynde’s picture

I like where this is headed. Have only reviewed the MR on the surface, but the new entity access operation makes sense. Thanks!

mxr576’s picture

Wow!

Tbh, I am a bit hesitant about introducing a new entity operation, although I am fully understanding why this is feels a compelling solution. Why am I hesitant? Because I have been involved several private conversations about what *view label" is and what not; and I am still not convinced that the majority of devs aware of that entity operation.

Would "view linked label" become a generic entity operation or username only? Should it be handled properly by all logic in core/contrib?

What I can also add that I have an extensive test coverage for username access in my module with a test controller that could be also useful foe debugging.

https://git.drupalcode.org/project/view_usernames/-/blob/1.x/tests/modul...

kristiaanvandeneynde changed the visibility of the branch 3506444-any-page-with to hidden.

catch’s picture

I can't think of a use case for the operation other than for user accounts.

godotislate’s picture

Issue summary: View changes
acbramley’s picture

Component: node system » user.module

Found while triaging Node issues, this definitely seems like a User module thing.

I haven't read the full thread but I'm a bit confused why we'd want to show a linked username if the user doesn't have access to view the profile? We'd be showing a link to a 403?

godotislate’s picture

I haven't read the full thread but I'm a bit confused why we'd want to show a linked username if the user doesn't have access to view the profile? We'd be showing a link to a 403?

No, the username label would not be linked at all. It would just be text.

The effective difference only applies to users who are viewing their own username's label. Access for the "view" operation is allowed for users with the "access user profiles" permission and for users viewing their own profile. Access for the "view linked label" operation is allowed for users with the "access user profiles" permission and ignores whether the user is viewing their own label. This means that the label is displayed as a link to all users, or displayed as text to all users. This removes the need for the user cache context, and it also makes the label display consistent to all users.

godotislate’s picture

catch’s picture

fwiw #40 sounds like how it should always have worked - there are plenty of ways for people to get to their own account.

smustgrave’s picture

Wanted to see what this one needs next?

godotislate’s picture

Wanted to see what this one needs next?

I resolved MR threads and rebase to get the tests to run again. I think it's ready.

needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new91 bytes

The Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".

This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

godotislate’s picture

Status: Needs work » Needs review

Re-based.

godotislate’s picture

Title: template_preprocess_username() doesn't handle cacheability correctly » UserThemeHooks::preprocessUsername() doesn't handle cacheability correctly

Updating title since function was moved.

dcam made their first commit to this issue’s fork.

dcam’s picture

Status: Needs review » Needs work
Issue tags: +Needs issue summary update

I rebased this to try and reproduce the issue during my review, but I'm having problems with manual testing. While reading through the issue comments (again) to try and get hints I found this quote from #29:

Keep in mind that if we fix user.module here before we fix node.module in another issue, we actually will introduce the critical issue I reported in the first place.

It sounds like this issue needs to be postponed to deal with the node module bug first. Is that right? Or have things changed? Has another issue been opened to fix the node module bug yet?

I'm also tagging this for an issue summary update because it is next-to-impossible to figure out what this issue is about from it. In particular, the Problem/Motivation section needs to be cleaned up, preferably with a short summary of the problem at hand.

For those reasons I'm setting the issue status to Needs Work. I reviewed the code. It looks good. I couldn't find anything to comment about.

catch’s picture

@dcam the node issue is #2528314: template_preprocess_node() does not add cacheability metadata but was marked as duplicate of #3458589: Deprecate $variables['page'] for node.html.twig and node_is_page(), however that issue definitely didn't fix the problem mentioned here.

catch’s picture

The relevant section in node preprocessNode() is:

  // Make created, uid and title fields available separately. Skip this custom
    // preprocessing if the field display is configurable and skipping has been
    // enabled.
    // @todo https://www.drupal.org/project/drupal/issues/3015623
    //   Eventually delete this code and matching template lines. Using
    //   $variables['content'] is more flexible and consistent.
    $submitted_configurable = $node->getFieldDefinition('created')->isDisplayConfigurable('view') || $node->getFieldDefinition('uid')->isDisplayConfigurable('view');
    if (!$skip_custom_preprocessing || !$submitted_configurable) {
      $variables['date'] = !empty($variables['elements']['created']) ? $this->renderer->render($variables['elements']['created']) : '';
      $variables['author_name'] = !empty($variables['elements']['uid']) ? $this->renderer->render($variables['elements']['uid']) : '';
      unset($variables['elements']['created'], $variables['elements']['uid']);
    }

That $variables['author_name'] is the problem identified above and it's very much still there.

dcam’s picture

@catch Thank you for clarifying that. I looked at that other issue, but I wasn't sure that it was about the same node problem since it:
A. Is a much older issue than this one, so it couldn't have been opened in response to this
B. Got closed as a duplicate.

godotislate’s picture

Issue summary: View changes
godotislate’s picture

Issue summary: View changes
Status: Needs work » Needs review
Issue tags: -Needs issue summary update

I've updated IS, and it's hopefully more clear.

I rebased this to try and reproduce the issue during my review, but I'm having problems with manual testing. While reading through the issue comments (again) to try and get hints I found this quote from #29:

Keep in mind that if we fix user.module here before we fix node.module in another issue, we actually will introduce the critical issue I reported in the first place.

It sounds like this issue needs to be postponed to deal with the node module bug first. Is that right? Or have things changed? Has another issue been opened to fix the node module bug yet?

The issue brought up in #29 is that bubbling cacheable metadata correctly from the preprocess method would bubble the user cache context, which is very undesirable. We're addressing that here with the introduction of the view linked label operation, which is different from the view operation, in that we don't care if the viewing user and the viewed user are same. The UI experience will be that all users who can't access user profiles see the user name as static text, all user who can access user profiles see the user name as a link.

godotislate’s picture

Just in case, I also added a CR for the 'view linked label' entity operation: https://www.drupal.org/node/3565758

godotislate’s picture

One additional note: While access to the 'view label' operation is granted to all users in UserAccessControlHandler::checkAccess(), I wonder whether it needs to be accounted for here, in cases where user access control handler is overridden or 'view label' access is otherwise modified. Drupal\user\Plugin\Field\FieldFormatter\AuthorFormatter, which uses the username theme element, has its own access check against 'view label', so maybe it makes sense that the expectation in any use case is that access to view the user name at all is checked before the username theme element is added?

dcam’s picture

Status: Needs review » Needs work
Related issues: +#849602: Update 'username' theme template to use 'view label' operation.

@godotislate, thank you for indulging my request for more and better information. I understand it much better now.

I've updated IS, and it's hopefully more clear.

Yes, it is. I don't know where I went wrong with my manual testing previously because I think I did most of the things in the steps to reproduce, but I wasn't getting the cached linked usernames. This time I was able to reproduce the problem accurately with your new instructions.

The issue brought up in #29 is that bubbling cacheable metadata correctly from the preprocess method would bubble the user cache context, which is very undesirable. We're addressing that here with the introduction of the view linked label operation...

Got it. Obviously I didn't put two and two together and understand that the new operation was meant to correct that problem. Thank you for taking the time to explain it to me.

The new change record looks good to me.

With my better understanding of the issue I re-reviewed the code. It still looks good to me overall. I only found one documentation issue to nitpick. I hope you don't mind me setting this to Needs Work for that.

Finally, I noticed #849602: Update 'username' theme template to use 'view label' operation. in the Needs Review queue earlier today. I checked its MR and it is modifying the same hook. These two will conflict with each other.

dcam’s picture

Status: Needs work » Reviewed & tested by the community

Ok, we cross-posted. My suggestion was already applied. So I'm going to go ahead and RTBC this.

needs-review-queue-bot’s picture

Status: Reviewed & tested by the community » Needs work
StatusFileSize
new91 bytes

The Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".

This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

godotislate’s picture

Version: 11.x-dev » main
Status: Needs work » Reviewed & tested by the community

Rebased and set this issue version to main.

  • catch committed 4070392d on 11.x
    fix: #3506444 UserThemeHooks::preprocessUsername() doesn't handle...

  • catch committed 6d59445f on main
    fix: #3506444 UserThemeHooks::preprocessUsername() doesn't handle...
catch’s picture

Version: main » 11.x-dev
Status: Reviewed & tested by the community » Fixed

Committed/pushed to main and 11.x, thanks!

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.

berdir’s picture

Note: This could have some tricky side effects in custom/contrib code if they did something special on the previously used operation. We noticed #3588357: Handle new "view linked label" access operation in our performance tests, which is minor, but there might be cases where extra access checks either allowed or disallowed access, which now no longer works. It's likely just a bug and not a security issue for them, as it just controls whether or not there is a link, but still a bit concerning.

Maybe the CR can more clearly mention that access hooks might need to handle this operation.