diff --git a/core/lib/Drupal/Core/Session/AccountInterface.php b/core/lib/Drupal/Core/Session/AccountInterface.php
index 6fdd60356a0882e5657c0655d9411b4dbb76934a..d6d10d79a9fdf8021ece37b7197b8bfadc3bdedd 100644
--- a/core/lib/Drupal/Core/Session/AccountInterface.php
+++ b/core/lib/Drupal/Core/Session/AccountInterface.php
@@ -50,7 +50,7 @@ public function getRoles($exclude_locked_roles = FALSE);
    * @return bool
    *   TRUE if the user has the permission, FALSE otherwise.
    */
-  public function hasPermission($permission);
+  public function hasPermission(/* string */$permission);
 
   /**
    * Returns TRUE if the account is authenticated.
diff --git a/core/lib/Drupal/Core/Session/UserSession.php b/core/lib/Drupal/Core/Session/UserSession.php
index 10ae41e5de2603962a3a9a602ad5abc164eebc7c..91787c0ba1cd00fc8baa952dde42e5d12fa4245a 100644
--- a/core/lib/Drupal/Core/Session/UserSession.php
+++ b/core/lib/Drupal/Core/Session/UserSession.php
@@ -119,7 +119,11 @@ public function hasRole(string $rid): bool {
   /**
    * {@inheritdoc}
    */
-  public function hasPermission($permission) {
+  public function hasPermission(/* string */$permission) {
+    if (!is_string($permission)) {
+      @trigger_error('Calling ' . __METHOD__ . '() with a $permission parameter of type other than string is deprecated in drupal:10.3.0 and will cause an error in drupal:11.0.0. See https://www.drupal.org/node/3411485', E_USER_DEPRECATED);
+      return FALSE;
+    }
     return \Drupal::service('permission_checker')->hasPermission($permission, $this);
   }
 
diff --git a/core/modules/user/src/Entity/User.php b/core/modules/user/src/Entity/User.php
index 2af4c9b846d0344528ca667366f7d30a04344b64..f03b4d14e4a4626b8882195a47793951111a0130 100644
--- a/core/modules/user/src/Entity/User.php
+++ b/core/modules/user/src/Entity/User.php
@@ -224,7 +224,11 @@ public function removeRole($rid) {
   /**
    * {@inheritdoc}
    */
-  public function hasPermission($permission) {
+  public function hasPermission(/* string */$permission) {
+    if (!is_string($permission)) {
+      @trigger_error('Calling ' . __METHOD__ . '() with a $permission parameter of type other than string is deprecated in drupal:10.3.0 and will cause an error in drupal:11.0.0. See https://www.drupal.org/node/3411485', E_USER_DEPRECATED);
+      return FALSE;
+    }
     return \Drupal::service('permission_checker')->hasPermission($permission, $this);
   }
 
diff --git a/core/tests/Drupal/Tests/Core/Session/UserSessionTest.php b/core/tests/Drupal/Tests/Core/Session/UserSessionTest.php
index b55cc05393ad9821f66506928f2b7d6a71945921..ef01736b764a68aa1a9db0d164cba03036195026 100644
--- a/core/tests/Drupal/Tests/Core/Session/UserSessionTest.php
+++ b/core/tests/Drupal/Tests/Core/Session/UserSessionTest.php
@@ -10,6 +10,7 @@
 use Drupal\Core\Session\PermissionChecker;
 use Drupal\Core\Session\UserSession;
 use Drupal\Tests\UnitTestCase;
+use Drupal\user\Entity\User;
 use Drupal\user\RoleInterface;
 
 /**
@@ -180,4 +181,19 @@ public function testHasRole() {
     $this->assertTrue($this->users['user_last']->hasRole(RoleInterface::ANONYMOUS_ID));
   }
 
+  /**
+   * Tests deprecation when permission is not a string.
+   *
+   * @covers ::hasPermission
+   * @group legacy
+   */
+  public function testHasPermissionLegacy() {
+    $this->expectDeprecation('Calling Drupal\Core\Session\UserSession::hasPermission() with a $permission parameter of type other than string is deprecated in drupal:10.3.0 and will cause an error in drupal:11.0.0. See https://www.drupal.org/node/3411485');
+    $this->assertFalse((new UserSession())->hasPermission(NULL));
+    $this->expectDeprecation('Calling Drupal\user\Entity\User::hasPermission() with a $permission parameter of type other than string is deprecated in drupal:10.3.0 and will cause an error in drupal:11.0.0. See https://www.drupal.org/node/3411485');
+    $reflection = new \ReflectionClass(User::class);
+    $user = $reflection->newInstanceWithoutConstructor();
+    $this->assertFalse($user->hasPermission(NULL));
+  }
+
 }