diff --git a/lib/classes/CSRFProtection.php b/lib/classes/CSRFProtection.php
index 440919efe92318f144bf51f0af44dfc8933a8863..56d6e4cc836786841ba34b02fe982fcadd01573b 100644
--- a/lib/classes/CSRFProtection.php
+++ b/lib/classes/CSRFProtection.php
@@ -44,6 +44,35 @@ class CSRFProtection
 
     const AJAX_TOKEN = 'HTTP_X_CSRF_TOKEN';
 
+    protected static $storage = null;
+
+    /**
+     * Set a storage to use.
+     *
+     * @param $storage
+     */
+    public static function setStorage(&$storage): void
+    {
+        self::$storage = &$storage;
+    }
+
+    /**
+     * Returns a reference to the used storage.
+     *
+     * @return array|null
+     */
+    public static function &getStorage()
+    {
+        if (!isset(self::$storage)) {
+            // w/o a session, throw an exception since we cannot use it
+            if (session_id() === '') {
+                throw new SessionRequiredException();
+            }
+
+            self::$storage = $_SESSION;
+        }
+        return self::$storage;
+    }
 
     /**
      * This checks the request and throws an InvalidSecurityTokenException if
@@ -118,17 +147,14 @@ class CSRFProtection
      */
     public static function token()
     {
-        // w/o a session, throw an exception
-        if (session_id() === '') {
-            throw new SessionRequiredException();
-        }
+        $storage = &self::getStorage();
 
         // create a token, if there is none
-        if (!isset($_SESSION[self::TOKEN])) {
-            $_SESSION[self::TOKEN] = base64_encode(random_bytes(32));
+        if (!isset($storage[self::TOKEN])) {
+            $storage[self::TOKEN] = base64_encode(random_bytes(32));
         }
 
-        return $_SESSION[self::TOKEN];
+        return $storage[self::TOKEN];
     }
 
     /**
diff --git a/lib/classes/StudipCoreFormat.php b/lib/classes/StudipCoreFormat.php
index 4d4b14b855fe4952027e0edfc4fec333f3a6f791..24c4ddcdf62e17e074f47c4320bb18264222b8b0 100644
--- a/lib/classes/StudipCoreFormat.php
+++ b/lib/classes/StudipCoreFormat.php
@@ -515,8 +515,6 @@ class StudipCoreFormat extends TextFormat
         $email = $matches[2];
         $domain = $matches[3];
 
-        $intern = $domain === $_SERVER['HTTP_HOST'];
-
         return sprintf('<a href="mailto:%1$s">%2$s</a>',
             $email,
             $link_text
@@ -567,6 +565,7 @@ class StudipCoreFormat extends TextFormat
         $intern = false;
         if (
             in_array($pu['scheme'], ['http', 'https'])
+            && isset($_SERVER['HTTP_HOST'])
             && (
                 !isset($pu['host'])
                 || $pu['host'] === $_SERVER['HTTP_HOST']
diff --git a/lib/classes/StudipPDO.class.php b/lib/classes/StudipPDO.class.php
index 3fe07188efb152f50d033fe867e66166447d2852..08012b105456b947d18b24e3372f2d7c8f813673 100644
--- a/lib/classes/StudipPDO.class.php
+++ b/lib/classes/StudipPDO.class.php
@@ -83,6 +83,7 @@ class StudipPDO extends PDO
             // split string into parts at quotes and backslash
             $parts = preg_split('/([\\\\"\'])/', $statement, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
             $result = '';
+            $quote_chr = null;
 
             for ($part = current($parts); $part !== false; $part = next($parts)) {
                 // inside quotes, "" is ", '' is ' and \x is x
diff --git a/lib/classes/Visibility.php b/lib/classes/Visibility.php
index ce191d2ab8f4d8a81b917ea4fa029dc752fe8b80..1b8723011523852c6c1269117b08035befa0bc49 100644
--- a/lib/classes/Visibility.php
+++ b/lib/classes/Visibility.php
@@ -500,8 +500,8 @@ class Visibility
      */
     private static function getUser(&$user)
     {
-        if ($user == null) {
-            $user = $GLOBALS['user']->user_id;
+        if (!$user && User::findCurrent()) {
+            $user = User::findCurrent()->id;
         }
     }
 
diff --git a/lib/models/CronjobSchedule.class.php b/lib/models/CronjobSchedule.class.php
index 6fcb68ff9651936362af1eff40ab6b7131c498c3..4304be1717948f7ec5012e83fbc7ac50fc8d2cfe 100644
--- a/lib/models/CronjobSchedule.class.php
+++ b/lib/models/CronjobSchedule.class.php
@@ -130,7 +130,7 @@ class CronjobSchedule extends SimpleORMap
         }
         if (in_array($type, ['after_initialize', 'after_store']) && is_string($this->parameters)) {
             $parameters = json_decode($this->parameters, true) ?: [];
-            if ($this->task->valid) {
+            if ($this->task && $this->task->valid) {
                 $default_parameters = $this->task->extractDefaultParameters();
                 foreach ($default_parameters as $key => $value) {
                     if (!isset($parameters[$key])) {
diff --git a/lib/models/SimpleORMap.class.php b/lib/models/SimpleORMap.class.php
index 3ff4cc083287d0c08a24f3cbf7ca6380e6272517..8f951b4abc33d03e8d498fada7ce1fc436393a22 100644
--- a/lib/models/SimpleORMap.class.php
+++ b/lib/models/SimpleORMap.class.php
@@ -863,7 +863,7 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
         if (is_array($id_or_object)) {
             $pk = static::pk();
             $key_values = [];
-            foreach($pk as $key) {
+            foreach ($pk as $key) {
                 if (array_key_exists($key, $id_or_object)) {
                     $key_values[] = $id_or_object[$key];
                 }
@@ -874,6 +874,8 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
                 } else {
                     $id = $key_values;
                 }
+            } else {
+                $id = null;
             }
         } else {
             $id = $id_or_object;
diff --git a/lib/visual.inc.php b/lib/visual.inc.php
index 30f99497519c416ebed424481e0513725953bd31..5cef921b16dbf8e147bbfdc13cbca3d4e61e2566 100644
--- a/lib/visual.inc.php
+++ b/lib/visual.inc.php
@@ -294,9 +294,9 @@ function isLinkIntern($url) {
         return true;
     }
 
-    return in_array($pum['scheme'] ?? null, ['https', 'http', NULL], true)
-        && in_array($pum['host'] ?? null, [$_SERVER['SERVER_NAME'], NULL], true)
-        && in_array($pum['port'] ?? null, [$_SERVER['SERVER_PORT'], NULL], true)
+    return in_array($pum['scheme'] ?? null, ['https', 'http', null], true)
+        && in_array($pum['host'] ?? null, [$_SERVER['SERVER_NAME'] ?? null, null], true)
+        && in_array($pum['port'] ?? null, [$_SERVER['SERVER_PORT'] ?? null, null], true)
         && mb_strpos($pum['path'] ?? '', $GLOBALS['CANONICAL_RELATIVE_PATH_STUDIP']) === 0;
 }
 
diff --git a/tests/unit/lib/classes/CsrfProtectionTest.php b/tests/unit/lib/classes/CsrfProtectionTest.php
index 1a74598188b1e231328244316b691643d55edd7a..69bc7a61960a4e21e3e10d6c3021205fe3f95e66 100644
--- a/tests/unit/lib/classes/CsrfProtectionTest.php
+++ b/tests/unit/lib/classes/CsrfProtectionTest.php
@@ -12,27 +12,18 @@
 
 class CSRFProtectionTokenTest extends \Codeception\Test\Unit
 {
-    private $original_session;
+    use CsrfProtectionSessionTrait;
 
     function setUp(): void
     {
-        if (session_id() === '') {
-            session_id("test-session");
-        }
-        $this->original_session = $_SESSION;
-        $_SESSION = [];
-    }
-
-    function tearDown(): void
-    {
-        $_SESSION = $this->original_session;
+        $this->initializeTokenStorage();
     }
 
     function testTokenGeneration()
     {
-        $this->assertEquals(sizeof($_SESSION), 0);
+        $this->assertEquals(count($this->storage), 0);
         CSRFProtection::token();
-        $this->assertEquals(sizeof($_SESSION), 1);
+        $this->assertEquals(count($this->storage), 1);
     }
 
     function testTokenIdentity()
@@ -44,7 +35,7 @@ class CSRFProtectionTokenTest extends \Codeception\Test\Unit
     {
         $token1 = CSRFProtection::token();
 
-        $_SESSION = [];
+        $this->storage = [];
 
         $token2 = CSRFProtection::token();
 
@@ -66,16 +57,17 @@ class CSRFProtectionTokenTest extends \Codeception\Test\Unit
 
 class CSRFRequestTest extends \Codeception\Test\Unit
 {
+    use CsrfProtectionSessionTrait;
+
     private $original_state;
     private $token;
 
     function setUp(): void
     {
-        if (session_id() === '') {
-            session_id("test-session");
-        }
-        $this->original_state = [$_SESSION, $_POST, $_SERVER];
-        $_SESSION = [];
+        $this->initializeTokenStorage();
+
+        $this->original_state = [$_POST, $_SERVER];
+
         $_POST = [];
         $this->token = CSRFProtection::token();
         $_SERVER['HTTP_X_REQUESTED_WITH'] = null;
@@ -83,7 +75,7 @@ class CSRFRequestTest extends \Codeception\Test\Unit
 
     function tearDown(): void
     {
-        list($_SESSION, $_POST, $_SERVER) = $this->original_state;
+        [$_POST, $_SERVER] = $this->original_state;
     }
 
     function testInvalidUnsafeRequest()
@@ -96,7 +88,7 @@ class CSRFRequestTest extends \Codeception\Test\Unit
     function testValidUnsafeRequest()
     {
         $_SERVER['REQUEST_METHOD'] = 'POST';
-        $_POST['security_token'] = $this->token;
+        $_POST[CSRFProtection::TOKEN] = $this->token;
         CSRFProtection::verifyUnsafeRequest();
         $this->assertTrue(true);
     }
@@ -134,3 +126,13 @@ class CSRFRequestTest extends \Codeception\Test\Unit
         $this->assertTrue(true);
     }
 }
+
+trait CsrfProtectionSessionTrait
+{
+    protected $storage = [];
+
+    protected function initializeTokenStorage()
+    {
+        CSRFProtection::setStorage($this->storage);
+    }
+}
diff --git a/tests/unit/lib/classes/MigrationTest.php b/tests/unit/lib/classes/MigrationTest.php
index dd78ac7ed7df67e1de1f426202a13989db736dd1..444ebf2fe8e5d5ebcdb3bdbd3da52d289be10c46 100644
--- a/tests/unit/lib/classes/MigrationTest.php
+++ b/tests/unit/lib/classes/MigrationTest.php
@@ -58,7 +58,7 @@ class MigrationTest extends \Codeception\Test\Unit
 
             public function get($branch = 0)
             {
-                return $this->versions[$branch];
+                return $this->versions[$branch] ?? 0;
             }
 
             public function set($version, $branch = 0)
diff --git a/tests/unit/lib/classes/TextFormatTest.php b/tests/unit/lib/classes/TextFormatTest.php
index 2174bb9dd56a7212e57d3952cccb3f9bb9f558e8..0d5007621bab3c480b0731885c6e516f9ac4abc4 100644
--- a/tests/unit/lib/classes/TextFormatTest.php
+++ b/tests/unit/lib/classes/TextFormatTest.php
@@ -101,6 +101,7 @@ function markupList($markup, $matches)
     $rows = explode("\n", rtrim($matches[0]));
     $indent = 0;
 
+    $result = '';
     foreach ($rows as $row) {
         list($level, $text) = explode(' ', $row, 2);
         $level = mb_strlen($level);