diff --git a/composer.json b/composer.json
index 88a2abcf0e1b35d08c262d7fcf74fcfe2c24fe7d..ca8d9831fe7a72e5783d477c04971077f67ab926 100644
--- a/composer.json
+++ b/composer.json
@@ -95,11 +95,8 @@
     "require-dev": {
         "ext-curl": "*",
         "mikey179/vfsstream": "~1.6",
-        "phpunit/phpunit": "~7.5",
-        "sensiolabs/security-checker": "^6.0.3",
         "simplesamlphp/simplesamlphp-test-framework": "^0.1.2",
-        "squizlabs/php_codesniffer": "^3.5",
-        "vimeo/psalm": "~3.13"
+        "vimeo/psalm": "~3.14"
     },
     "suggest": {
         "predis/predis": "Needed if a Redis server is used to store session information",
diff --git a/lib/SimpleSAML/Metadata/SAMLBuilder.php b/lib/SimpleSAML/Metadata/SAMLBuilder.php
index 60adb3003c5aa1c600a9d2f90ccb5e195650d113..f038854a25f1ee50ce7476d8809da177352ebfb9 100644
--- a/lib/SimpleSAML/Metadata/SAMLBuilder.php
+++ b/lib/SimpleSAML/Metadata/SAMLBuilder.php
@@ -156,7 +156,10 @@ class SAMLBuilder
         $metadata = Configuration::loadFromArray($metadata, $metadata['entityid']);
         $defaultEndpoint = $metadata->getDefaultEndpoint('SingleSignOnService');
 
-        /** @psalm-suppress UndefinedClass */
+        /**
+         * @psalm-var \SAML2\XML\md\RoleDescriptor $e
+         * @psalm-suppress UndefinedClass
+         */
         $e = new SecurityTokenServiceType();
         $e->setLocation($defaultEndpoint['Location']);
 
diff --git a/lib/SimpleSAML/Session.php b/lib/SimpleSAML/Session.php
index ea78e0eca9c5042bf51043c1aec50692ab88a356..927f74e8b854f08eb7e676ec8448765699b0b350 100644
--- a/lib/SimpleSAML/Session.php
+++ b/lib/SimpleSAML/Session.php
@@ -47,8 +47,10 @@ class Session implements \Serializable, Utils\ClearableState
      * This variable holds the instance of the session - Singleton approach.
      *
      * Warning: do not set the instance manually, call Session::load() instead.
+     *
+     * @var \SimpleSAML\Session|null
      */
-    private static $instance;
+    private static $instance = null;
 
     /**
      * The global configuration.
diff --git a/lib/SimpleSAML/SessionHandlerPHP.php b/lib/SimpleSAML/SessionHandlerPHP.php
index 3a4f2ed18b47a55d9bde9e9e69e444a8e4a2f6b9..cfde6bf262b4ec148e5140cb5684dd8bf0d57c1a 100644
--- a/lib/SimpleSAML/SessionHandlerPHP.php
+++ b/lib/SimpleSAML/SessionHandlerPHP.php
@@ -80,7 +80,7 @@ class SessionHandlerPHP extends SessionHandler
 
         if (!headers_sent()) {
             if (version_compare(PHP_VERSION, '7.3.0', '>=')) {
-                /** @psalm-suppress InvalidArgument  This annotation may be removed in Psalm >=3.0.15 */
+                /** @psalm-suppress InvalidArgument */
                 session_set_cookie_params([
                     'lifetime' => $params['lifetime'],
                     'path' => $params['path'],
@@ -372,7 +372,7 @@ class SessionHandlerPHP extends SessionHandler
         }
 
         if (version_compare(PHP_VERSION, '7.3.0', '>=')) {
-            /** @psalm-suppress InvalidArgument  This annotation may be removed in Psalm >=3.0.15 */
+            /** @psalm-suppress InvalidArgument */
             session_set_cookie_params($cookieParams);
         } else {
             session_set_cookie_params(
diff --git a/lib/SimpleSAML/Utilities.php b/lib/SimpleSAML/Utilities.php
index be12e719b5598fd6eae23fe9ac5b3a314bc0e0ba..e395084bb4ea680b5d11b171767ee7e0a7627def 100644
--- a/lib/SimpleSAML/Utilities.php
+++ b/lib/SimpleSAML/Utilities.php
@@ -237,8 +237,6 @@ class Utilities
      */
     private static function doRedirect(string $url, array $parameters = []): void
     {
-        Assert::NotEmpty($url);
-
         if (!empty($parameters)) {
             $url = self::addURLparameter($url, $parameters);
         }
diff --git a/lib/SimpleSAML/Utils/HTTP.php b/lib/SimpleSAML/Utils/HTTP.php
index 141a2233b3c30242b198ec987c0b266891358c1e..3fdacdfc001c98f3e7cc7c705eeeb1c028dac4d3 100644
--- a/lib/SimpleSAML/Utils/HTTP.php
+++ b/lib/SimpleSAML/Utils/HTTP.php
@@ -1206,7 +1206,7 @@ class HTTP
         if (version_compare(PHP_VERSION, '7.3.0', '>=')) {
             /* use the new options array for PHP >= 7.3 */
             if ($params['raw']) {
-                /** @psalm-suppress InvalidArgument  Remove when Psalm >= 3.4.10 */
+                /** @psalm-suppress InvalidArgument */
                 $success = @setrawcookie(
                     $name,
                     $value,
@@ -1220,7 +1220,7 @@ class HTTP
                     ]
                 );
             } else {
-                /** @psalm-suppress InvalidArgument  Remove when Psalm >= 3.4.10 */
+                /** @psalm-suppress InvalidArgument */
                 $success = @setcookie(
                     $name,
                     $value,