diff --git a/core/modules/user/config/schema/user.schema.yml b/core/modules/user/config/schema/user.schema.yml
index 99285373c3d16604d6ce5422cf3ef24398a55151..b778163bf5c0a85a6dd3351f1db4987d506679a3 100644
--- a/core/modules/user/config/schema/user.schema.yml
+++ b/core/modules/user/config/schema/user.schema.yml
@@ -122,6 +122,7 @@ user.role.*:
     permissions:
       type: sequence
       label: 'Permissions'
+      orderby: value
       sequence:
         type: string
         label: 'Permission'
diff --git a/core/modules/user/src/Entity/Role.php b/core/modules/user/src/Entity/Role.php
index 7e38a43e5a2a868c00d2a9f3c0bcebe6ccfe57a0..1219cef9ef18f38938760bb065b6adcfe7c5979d 100644
--- a/core/modules/user/src/Entity/Role.php
+++ b/core/modules/user/src/Entity/Role.php
@@ -185,12 +185,6 @@ public function preSave(EntityStorageInterface $storage) {
       });
       $this->weight = $max + 1;
     }
-
-    if (!$this->isSyncing()) {
-      // Permissions are always ordered alphabetically to avoid conflicts in the
-      // exported configuration.
-      sort($this->permissions);
-    }
   }
 
   /**
diff --git a/core/modules/user/tests/src/Kernel/UserRoleEntityTest.php b/core/modules/user/tests/src/Kernel/UserRoleEntityTest.php
index 492fdac20faeb85e45859fcfa5d186b97cf91747..c2d6b6d7ba292ae41ba83b4abef8a8bd657c48d6 100644
--- a/core/modules/user/tests/src/Kernel/UserRoleEntityTest.php
+++ b/core/modules/user/tests/src/Kernel/UserRoleEntityTest.php
@@ -45,4 +45,16 @@ public function testGrantingNonExistentPermission() {
       ->save();
   }
 
+  public function testPermissionRevokeAndConfigSync() {
+    $role = Role::create(['id' => 'test_role', 'label' => 'Test role']);
+    $role->setSyncing(TRUE);
+    $role->grantPermission('a')
+      ->grantPermission('b')
+      ->grantPermission('c')
+      ->save();
+    $this->assertSame(['a', 'b', 'c'], $role->getPermissions());
+    $role->revokePermission('b')->save();
+    $this->assertSame(['a', 'c'], $role->getPermissions());
+  }
+
 }
diff --git a/core/modules/user/user.post_update.php b/core/modules/user/user.post_update.php
index f1b6da9bc9c16d85c1711001838b1d741f805b1f..e87f6ffcf392e0f29146478697d0be5e9e144c46 100644
--- a/core/modules/user/user.post_update.php
+++ b/core/modules/user/user.post_update.php
@@ -5,6 +5,9 @@
  * Post update functions for User module.
  */
 
+use Drupal\Core\Config\Entity\ConfigEntityUpdater;
+use Drupal\user\Entity\Role;
+
 /**
  * Implements hook_removed_post_updates().
  */
@@ -14,3 +17,14 @@ function user_removed_post_updates() {
     'user_post_update_update_roles' => '10.0.0',
   ];
 }
+
+/**
+ * Ensure permissions stored in role configuration are sorted using the schema.
+ */
+function user_post_update_sort_permissions(&$sandbox = NULL) {
+  \Drupal::classResolver(ConfigEntityUpdater::class)->update($sandbox, 'user_role', function (Role $role) {
+    $permissions = $role->getPermissions();
+    sort($permissions);
+    return $permissions !== $role->getPermissions();
+  });
+}