UserRolesCacheContext can lead to poisoned cache returns for user 1

Created on 27 March 2024, about 1 year ago

Problem/Motivation

This is a public follow-up to a security issue as it was deemed low risk in the private security issue.
11/25 (Moderately Critical) AC:Complex/A:Admin/CI:Some/II:Some/E:Theoretical/TD:Default

Steps to reproduce

  • Create a block that shows your user roles, obviously vary it by user.roles
  • With only the Admin role, visit a page with said block as UID 1, see that it lists the Admin role
  • Assign another role (e.g. Editor) to UID 1
  • Visit the same page as before and see that the block lists the Admin, but not Editor role

This also works the other way around, where roles are revoked and the more permissive result is still shown, which is why it was reported as a security issue. In some modules, this is leading to unexpected results because said modules have code that relies on what roles you have rather than what permissions you have. For user 1 this is leading to confusing outcomes.

Proposed resolution

Remove the special user 1 string from the following code:

  public function getContext($role = NULL) {
    // User 1 does not actually have any special behavior for roles; this is
    // added as additional security and backwards compatibility protection for
    // SA-CORE-2015-002.
    // @todo Remove in Drupal 9.0.0.
    if ($this->user->id() == 1) {
      return 'is-super-user';
    }
    if ($role === NULL) {
      return implode(',', $this->user->getRoles());
    }
    else {
      return (in_array($role, $this->user->getRoles()) ? 'true' : 'false');
    }
  }

Especially now that we have/are about to switch to access policies, which will no longer hard-code UID 1's special behavior but rather make it a service that you can opt out of.

We've always said not to use user.roles when you should be using user.permissions, but we have to acknowledge that there might be some code out there that still did this. However, said code will remain functional (yet a security risk) but it will no longer exhibit the buggy behavior described here when it comes to user 1.

When we work on πŸ“Œ Add a container parameter that can remove the special behavior of UID#1 Fixed once πŸ“Œ Implement the new access policy API Needs work has landed, we can run all tests with UID 1's special powers turned off, at which point we can rest assured core should no longer hard-code any special UID 1 exceptions like was done here.

Remaining tasks

  • Remove the special string from the cache context
  • Perhaps update or remove RenderCacheTest.php

User interface changes

None

API changes

UID 1 no longer gets a special value from the user.roles cache context

Data model changes

None

Release notes snippet

UID 1 no longer gets a special value from the user.roles cache context

πŸ› Bug report
Status

Active

Version

11.0 πŸ”₯

Component
CacheΒ  β†’

Last updated 1 day ago

Created by

πŸ‡§πŸ‡ͺBelgium kristiaanvandeneynde Antwerp, Belgium

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

Production build 0.71.5 2024