CVE-2024-27937: Insufficient Information (NVD-CWE-noinfo)
value: GLPI is a Free Asset and IT Management Software package, Data center management, ITIL Service Desk, licenses tracking and software auditing. An authenticated user can obtain the email address of all GLPI users. This issue has been patched in version 10.0.13.

CWE description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
Published: 2024-03-18T16:15Z
Repository: https://github.com/glpi-project/glpi
Language: PHP
Files changed: ajax/dropdownAllItems.php, ajax/dropdownConnect.php, ajax/dropdownItilActors.php, ajax/dropdownProjectTaskTicket.php, ajax/dropdownSoftwareLicense.php, ajax/dropdownTicketCategories.php, ajax/dropdownTrackingDeviceType.php, ajax/updateTrackingDeviceType.php, src/CommonDBRelation.php, src/CommonITILObject.php, src/Consumable.php, src/Dropdown.php, src/Item_Ticket.php, src/NetworkPortInstantiation.php, src/Session.php, src/User.php, tests/functional/Session.php
Commit date: 2024-03-13 08:16:53 +0100
Commit message: Merge pull request from GHSA-98qw-hpg3-2hpj

* Filter entity restriction in dropdowns to match active entities

* Handle string values in entities filtering
Diff: diff --git a/ajax/dropdownAllItems.php b/ajax/dropdownAllItems.php
index acdb2c10027c..882b0d38ee7b 100644
--- a/ajax/dropdownAllItems.php
+++ b/ajax/dropdownAllItems.php
@@ -41,10 +41,14 @@ include('../inc/includes.php');
 header("Content-Type: text/html; charset=UTF-8");
 Html::header_nocache();
 
 Session::checkCentralAccess();
 
+if (isset($_POST['entity_restrict'])) {
+    $_POST['entity_restrict'] = Session::getMatchingActiveEntities($_POST['entity_restrict']);
+}
+
 // Make a select box
 if ($_POST["idtable"] && class_exists($_POST["idtable"])) {
    // Link to user for search only > normal users
     $link = "getDropdownValue.php";
 
diff --git a/ajax/dropdownConnect.php b/ajax/dropdownConnect.php
index caeafbf522f1..b5256ef26e1e 100644
--- a/ajax/dropdownConnect.php
+++ b/ajax/dropdownConnect.php
@@ -50,9 +50,9 @@ $fromitem->checkGlobal(UPDATE);
 $used = $_POST["used"] ?? [];
 Computer_Item::dropdownConnect(
     $_POST["itemtype"],
     $_POST['fromtype'],
     $_POST['myname'],
-    $_POST["entity_restrict"],
+    Session::getMatchingActiveEntities($_POST['entity_restrict']),
     $_POST["onlyglobal"],
     $used
 );
diff --git a/ajax/dropdownItilActors.php b/ajax/dropdownItilActors.php
index e342bc71c190..33b6a91def99 100644
--- a/ajax/dropdownItilActors.php
+++ b/ajax/dropdownItilActors.php
@@ -63,11 +63,11 @@ if (
                         $right = 'id';
                     }
                 }
 
                 $options = ['name'        => '_itil_' . $_POST["actortype"] . '[users_id]',
-                    'entity'      => $_POST['entity_restrict'],
+                    'entity'      => Session::getMatchingActiveEntities($_POST['entity_restrict']),
                     'right'       => $right,
                     'rand'        => $rand,
                     'ldap_import' => true
                 ];
 
@@ -145,11 +145,11 @@ if (
                     $cond = ['is_watcher' => 1];
                 }
 
                 $param = [
                     'name'      => '_itil_' . $_POST["actortype"] . '[groups_id]',
-                    'entity'    => $_POST['entity_restrict'],
+                    'entity'    => Session::getMatchingActiveEntities($_POST['entity_restrict']),
                     'condition' => $cond,
                     'rand'      => $rand
                 ];
                 if (
                     ($_POST["itemtype"] == 'Ticket')
@@ -177,11 +177,11 @@ if (
 
                 break;
 
             case "supplier":
                 $options = ['name'      => '_itil_' . $_POST["actortype"] . '[suppliers_id]',
-                    'entity'    => $_POST['entity_restrict'],
+                    'entity'    => Session::getMatchingActiveEntities($_POST['entity_restrict']),
                     'rand'      => $rand
                 ];
                 if ($CFG_GLPI["notifications_mailing"]) {
                     $paramscomment = ['value'       => '__VALUE__',
                         'allow_email' => $withemail,
diff --git a/ajax/dropdownProjectTaskTicket.php b/ajax/dropdownProjectTaskTicket.php
index 104395c62d49..f90a6511c35d 100644
--- a/ajax/dropdownProjectTaskTicket.php
+++ b/ajax/dropdownProjectTaskTicket.php
@@ -49,11 +49,11 @@ if (isset($_POST["projects_id"])) {
     if ($_POST["projects_id"] > 0) {
         $condition['glpi_projecttasks.projects_id'] = $_POST['projects_id'];
     }
 
     $p = ['itemtype'     => ProjectTask::getType(),
-        'entity_restrict' => $_POST['entity_restrict'],
+        'entity_restrict' => Session::getMatchingActiveEntities($_POST['entity_restrict']),
         'myname'          => $_POST["myname"],
         'condition'       => $condition,
         'rand'            => $_POST["rand"]
     ];
 
diff --git a/ajax/dropdownSoftwareLicense.php b/ajax/dropdownSoftwareLicense.php
index 3bd82bd0b108..41d96aa53262 100644
--- a/ajax/dropdownSoftwareLicense.php
+++ b/ajax/dropdownSoftwareLicense.php
@@ -54,11 +54,11 @@ if ($_POST['softwares_id'] > 0) {
     $iterator = $DB->request([
         'DISTINCT'  => true,
         'FROM'      => 'glpi_softwarelicenses',
         'WHERE'     => [
             'glpi_softwarelicenses.softwares_id'   => (int)$_POST['softwares_id']
-        ] + getEntitiesRestrictCriteria('glpi_softwarelicenses', 'entities_id', $_POST['entity_restrict'], true),
+        ] + getEntitiesRestrictCriteria('glpi_softwarelicenses', 'entities_id', Session::getMatchingActiveEntities($_POST['entity_restrict']), true),
         'ORDERBY'   => 'name'
     ]);
     $number = count($iterator);
 
     $values = [];
diff --git a/ajax/dropdownTicketCategories.php b/ajax/dropdownTicketCategories.php
index d8377f1b9ade..eeb3f29f6626 100644
--- a/ajax/dropdownTicketCategories.php
+++ b/ajax/dropdownTicketCategories.php
@@ -39,11 +39,11 @@ if (strpos($_SERVER['PHP_SELF'], "dropdownTicketCategories.php")) {
     Html::header_nocache();
 } else if (!defined('GLPI_ROOT')) {
     die("Sorry. You can't access this file directly");
 }
 
-$opt = ['entity' => $_POST["entity_restrict"]];
+$opt = ['entity' => Session::getMatchingActiveEntities($_POST['entity_restrict'])];
 $condition  = [];
 
 if (Session::getCurrentInterface() == "helpdesk") {
     $condition['is_helpdeskvisible'] = 1;
 }
diff --git a/ajax/dropdownTrackingDeviceType.php b/ajax/dropdownTrackingDeviceType.php
index bdb2e3d40cd2..6863c61a0472 100644
--- a/ajax/dropdownTrackingDeviceType.php
+++ b/ajax/dropdownTrackingDeviceType.php
@@ -74,18 +74,18 @@ if ($isValidItemtype) {
          . "</span>";
     }
     $field_id = Html::cleanId("dropdown_" . $_POST['myname'] . $rand);
     $p = [
         'itemtype'            => $itemtype,
-        'entity_restrict'     => $_POST['entity_restrict'],
+        'entity_restrict'     => Session::getMatchingActiveEntities($_POST['entity_restrict']),
         'table'               => $table,
         'multiple'            => (int) ($_POST["multiple"] ?? 0) !== 0,
         'myname'              => $_POST["myname"],
         'rand'                => $_POST["rand"],
         'width'               => 'calc(100% - 25px)',
         '_idor_token'         => Session::getNewIDORToken($itemtype, [
-            'entity_restrict' => $_POST['entity_restrict'],
+            'entity_restrict' => Session::getMatchingActiveEntities($_POST['entity_restrict']),
         ]),
     ];
 
     if (isset($_POST["used"]) && !empty($_POST["used"])) {
         if (isset($_POST["used"][$itemtype])) {
diff --git a/ajax/updateTrackingDeviceType.php b/ajax/updateTrackingDeviceType.php
index 32f942321b81..de0a9aabdda9 100644
--- a/ajax/updateTrackingDeviceType.php
+++ b/ajax/updateTrackingDeviceType.php
@@ -38,8 +38,8 @@ include('../inc/includes.php');
 
 header("Content-Type: text/html; charset=UTF-8");
 Html::header_nocache();
 
 Session::checkRight("ticket", UPDATE);
-Item_Ticket::dropdownMyDevices($_POST["userID"], $_POST["entity_restrict"]);
+Item_Ticket::dropdownMyDevices($_POST["userID"], Session::getMatchingActiveEntities($_POST['entity_restrict']));
 
 Html::ajaxFooter();
diff --git a/src/CommonDBRelation.php b/src/CommonDBRelation.php
index 32708f2aae35..d2c4f4ef34db 100644
--- a/src/CommonDBRelation.php
+++ b/src/CommonDBRelation.php
@@ -1476,11 +1476,11 @@ abstract class CommonDBRelation extends CommonDBConnexity
                             Dropdown::showSelectItemFromItemtypes($options);
                         }
                     } else {
                         $options['name'] = 'peer_' . $peers_id;
                         if (isset($_POST['entity_restrict'])) {
-                            $options['entity'] = $_POST['entity_restrict'];
+                            $options['entity'] = Session::getMatchingActiveEntities($_POST['entity_restrict']);
                         }
                         if ($normalized_action == 'remove') {
                             $options['nochecklimit'] = true;
                         }
                         $dropdown_method = $specificities['dropdown_method_' . $peer_number];
diff --git a/src/CommonITILObject.php b/src/CommonITILObject.php
index 4d46f5d3b99d..833b1b3d8d7b 100644
--- a/src/CommonITILObject.php
+++ b/src/CommonITILObject.php
@@ -4946,11 +4946,11 @@ abstract class CommonITILObject extends CommonDBTM
             'name'   => $actor_name,
             'value'  => $options["_users_id_" . $typename],
             'right'  => $right,
             'rand'   => $rand,
             'width'  => "95%",
-            'entity' => $options['entities_id'] ?? $options['entity_restrict']
+            'entity' => Session::getMatchingActiveEntities($options['entities_id'] ?? $options['entity_restrict']),
         ];
 
        //only for active ldap and corresponding right
         $ldap_methods = getAllDataFromTable('glpi_authldaps', ['is_active' => 1]);
         if (
diff --git a/src/Consumable.php b/src/Consumable.php
index f6c7b10d9602..4ce7ca0b67de 100644
--- a/src/Consumable.php
+++ b/src/Consumable.php
@@ -204,11 +204,11 @@ class Consumable extends CommonDBChild
                     Dropdown::showSelectItemFromItemtypes(['itemtype_name'
                                                               => 'give_itemtype',
                         'items_id_name'
                                                               => 'give_items_id',
                         'entity_restrict'
-                                                              => $input["entities_id"],
+                                                              => Session::getMatchingActiveEntities($input["entities_id"]),
                         'itemtypes'
                                                               => $CFG_GLPI["consumables_types"]
                     ]);
                     echo "<br><br>" . Html::submit(
                         _x('button', 'Give'),
diff --git a/src/Dropdown.php b/src/Dropdown.php
index c5d48bbb7f8a..415a70623000 100644
--- a/src/Dropdown.php
+++ b/src/Dropdown.php
@@ -200,10 +200,11 @@ class Dropdown
                 $output .= "entity_sons options is not available with entity option as array";
             } else {
                 $params['entity'] = getSonsOf('glpi_entities', $params['entity']);
             }
         }
+        $params['entity'] = Session::getMatchingActiveEntities($params['entity']);
 
         $field_id = Html::cleanId("dropdown_" . $params['name'] . $params['rand']);
 
        // Manage condition
         if (!empty($params['condition'])) {
@@ -2623,11 +2624,13 @@ JAVASCRIPT;
        // check if asked itemtype is the one originaly requested by the form
         if (!Session::validateIDOR($post)) {
             return;
         }
 
-        if (
+        if (isset($post['entity_restrict']) && 'default' === $post['entity_restrict']) {
+            $post['entity_restrict'] = $_SESSION['glpiactiveentities'];
+        } elseif (
             isset($post["entity_restrict"])
             && !is_array($post["entity_restrict"])
             && (substr($post["entity_restrict"], 0, 1) === '[')
             && (substr($post["entity_restrict"], -1) === ']')
         ) {
@@ -2636,14 +2639,11 @@ JAVASCRIPT;
             if (is_array($decoded)) {
                 foreach ($decoded as $value) {
                     $entities[] = (int)$value;
                 }
             }
-            $post["entity_restrict"] = $entities;
-        }
-        if (isset($post['entity_restrict']) && 'default' === $post['entity_restrict']) {
-            $post['entity_restrict'] = $_SESSION['glpiactiveentities'];
+            $post["entity_restrict"] = Session::getMatchingActiveEntities($entities);
         }
 
        // Security
         if (!($item = getItemForItemtype($post['itemtype']))) {
             return;
@@ -3513,10 +3513,14 @@ JAVASCRIPT;
 
         if (!isset($post['fromtype']) || !($fromitem = getItemForItemtype($post['fromtype']))) {
             return;
         }
 
+        if (isset($post['entity_restrict'])) {
+            $post['entity_restrict'] = Session::getMatchingActiveEntities($post['entity_restrict']);
+        }
+
         $fromitem->checkGlobal(UPDATE);
         $used = [];
         if (isset($post["used"])) {
             $used = $post["used"];
 
@@ -3783,11 +3787,11 @@ JAVASCRIPT;
             $where['is_helpdesk_visible'] = 1;
         }
 
         if ($item->isEntityAssign()) {
             if (isset($post["entity_restrict"]) && ($post["entity_restrict"] >= 0)) {
-                $entity = $post["entity_restrict"];
+                $entity = Session::getMatchingActiveEntities($post['entity_restrict']);
             } else {
                 $entity = '';
             }
 
            // allow opening ticket on recursive object (printer, software, ...)
@@ -4021,10 +4025,11 @@ JAVASCRIPT;
             $result = [$user->fields];
         } else {
             $entity_restrict = -1;
             if (isset($post['entity_restrict'])) {
                 $entity_restrict = Toolbox::jsonDecode($post['entity_restrict']);
+                $entity_restrict = Session::getMatchingActiveEntities($entity_restrict);
             }
 
             $start  = intval(($post['page'] - 1) * $post['page_limit']);
             $searchText = (isset($post['searchText']) ? $post['searchText'] : null);
             $inactive_deleted = isset($post['inactive_deleted']) ? $post['inactive_deleted'] : 0;
@@ -4127,10 +4132,11 @@ JAVASCRIPT;
         $post = array_merge($defaults, $post);
 
         $entity_restrict = -1;
         if (isset($post['entity_restrict'])) {
             $entity_restrict = Toolbox::jsonDecode($post['entity_restrict']);
+            $entity_restrict = Session::getMatchingActiveEntities($entity_restrict);
         }
 
        // prevent instanciation of bad classes
         if (!is_subclass_of($post['itiltemplate_class'], 'ITILTemplate')) {
             return false;
diff --git a/src/Item_Ticket.php b/src/Item_Ticket.php
index f69e118fda83..7753d3ef3717 100644
--- a/src/Item_Ticket.php
+++ b/src/Item_Ticket.php
@@ -602,10 +602,12 @@ class Item_Ticket extends CommonItilObject_Item
 
         if ($userID == 0) {
             $userID = Session::getLoginUserID();
         }
 
+        $entity_restrict = Session::getMatchingActiveEntities($entity_restrict);
+
         $rand        = $params['rand'];
         $already_add = $params['used'];
 
         if ($_SESSION["glpiactiveprofile"]["helpdesk_hardware"] & pow(2, Ticket::HELPDESK_MY_HARDWARE)) {
             $my_devices = ['' => Dropdown::EMPTY_VALUE];
diff --git a/src/NetworkPortInstantiation.php b/src/NetworkPortInstantiation.php
index 242eb6bc9ad6..1225816ac014 100644
--- a/src/NetworkPortInstantiation.php
+++ b/src/NetworkPortInstantiation.php
@@ -1023,11 +1023,11 @@ class NetworkPortInstantiation extends CommonDBChild
 
         echo "<input type='hidden' name='NetworkPortConnect_networkports_id_1'value='$ID'>";
         $rand = Dropdown::showItemTypes('NetworkPortConnect_itemtype', $CFG_GLPI["networkport_types"]);
 
         $params = ['itemtype'           => '__VALUE__',
-            'entity_restrict'    => $p['entity'],
+            'entity_restrict'    => Session::getMatchingActiveEntities($p['entity']),
             'networkports_id'    => $ID,
             'comments'           => $p['comments'],
             'myname'             => $p['name'],
             'instantiation_type' => get_called_class()
         ];
diff --git a/src/Session.php b/src/Session.php
index 324d7971f1bb..15bf9fb2723f 100644
--- a/src/Session.php
+++ b/src/Session.php
@@ -1955,10 +1955,52 @@ class Session
     public static function getActiveEntity()
     {
         return $_SESSION['glpiactive_entity'] ?? 0;
     }
 
+    /**
+     * Filter given entities ID list to return only these tht are matching current active entities in session.
+     *
+     * @since 10.0.13
+     *
+     * @param int|int[] $entities_ids
+     *
+     * @return int|int[]
+     */
+    public static function getMatchingActiveEntities(/*int|array*/ $entities_ids)/*: int|array*/
+    {
+        if (
+            (int)$entities_ids === -1
+            || (is_array($entities_ids) && count($entities_ids) === 1 && (int)reset($entities_ids) === -1)
+        ) {
+            // Special value that is generally used to fallback to all active entities.
+            return $entities_ids;
+        }
+
+        if (!is_array($entities_ids) && !is_int($entities_ids) && !ctype_digit($entities_ids)) {
+            // Unexpected value type.
+            return [];
+        }
+
+        $active_entities_ids = $_SESSION['glpiactiveentities'] ?? [];
+
+        if (!is_array($entities_ids) && in_array((int)$entities_ids, $active_entities_ids, true)) {
+            return (int)$entities_ids;
+        }
+
+        $filtered = [];
+        foreach ((array)$entities_ids as $entity_id) {
+            if (
+                (is_int($entity_id) || ctype_digit($entity_id))
+                && in_array((int)$entity_id, $active_entities_ids, true)
+            ) {
+                $filtered[] = (int)$entity_id;
+            }
+        }
+        return $filtered;
+    }
+
     /**
      * Get recursive state of active entity selection.
      *
      * @since 9.5.5
      *
diff --git a/src/User.php b/src/User.php
index 4f137454f7c8..695fe4df5fc9 100644
--- a/src/User.php
+++ b/src/User.php
@@ -4615,17 +4615,19 @@ HTML;
         ) {
             $p['value'] = 0;
         }
 
         $output = '';
+
         if (!($p['entity'] < 0) && $p['entity_sons']) {
             if (is_array($p['entity'])) {
                 $output .= "entity_sons options is not available with array of entity";
             } else {
                 $p['entity'] = getSonsOf('glpi_entities', $p['entity']);
             }
         }
+        $p['entity'] = Session::getMatchingActiveEntities($p['entity']);
 
         // Make a select box with all glpi users
         $view_users = self::canView();
 
         $default = '';
diff --git a/tests/functional/Session.php b/tests/functional/Session.php
index 1f943edb72ab..8697f61de094 100644
--- a/tests/functional/Session.php
+++ b/tests/functional/Session.php
@@ -628,6 +628,97 @@ class Session extends \DbTestCase
         $this->login();
         // Set language to French to ensure we always get names back as en_GB regardless of the user's language
         \Session::loadLanguage('fr_FR');
         $this->string(\Session::getRightNameForError($module, $right))->isEqualTo($expected);
     }
+
+    protected function entitiesRestricProvider(): iterable
+    {
+        // Special case for -1
+        foreach ([-1, "-1", [-1], ["-1"]] as $value) {
+            yield [
+                'entity_restrict' => $value,
+                'active_entities' => [0, 1, 2, 3],
+                'result'          => is_array($value) ? [-1] : -1,
+            ];
+        }
+
+        // Integer input, matching
+        yield [
+            'entity_restrict' => 2,
+            'active_entities' => [0, 1, 2, 3],
+            'result'          => 2,
+        ];
+
+        // String input, matching
+        yield [
+            'entity_restrict' => '2',
+            'active_entities' => [0, 1, 2, 3],
+            'result'          => 2,
+        ];
+
+        // Integer input, NOT matching
+        yield [
+            'entity_restrict' => 7,
+            'active_entities' => [0, 1, 2, 3],
+            'result'          => [],
+        ];
+
+        // String input, matching
+        yield [
+            'entity_restrict' => '7',
+            'active_entities' => [0, 1, 2, 3],
+            'result'          => [],
+        ];
+
+        // Array input, ALL matching
+        yield [
+            'entity_restrict' => [0, '2', 3],
+            'active_entities' => [0, 1, 2, 3],
+            'result'          => [0, 2, 3],
+        ];
+
+        // Array input, PARTIAL matching
+        yield [
+            'entity_restrict' => [0, '2', 3, 12, 54, 96],
+            'active_entities' => [0, 1, 2, 3],
+            'result'          => [0, '2', 3],
+        ];
+
+        // Array input, NONE matching
+        yield [
+            'entity_restrict' => [0, '2', 3, 12, 54, 96],
+            'active_entities' => [1, 4],
+            'result'          => [],
+        ];
+
+        // Empty active entities
+        yield [
+            'entity_restrict' => [0, '2', 3, 12, 54, 96],
+            'active_entities' => null,
+            'result'          => [],
+        ];
+
+        // Unexpected unique value
+        yield [
+            'entity_restrict' => 'not a valid value',
+            'active_entities' => [0, 1, 2, 3],
+            'result'          => [],
+        ];
+
+        // Unexpected value in an array
+        yield [
+            'entity_restrict' => [0, 'not a valid value', 3],
+            'active_entities' => [0, 1, 2, 3],
+            'result'          => [0, 3],
+        ];
+    }
+
+    /**
+     * @dataProvider entitiesRestricProvider
+     */
+    public function testGetMatchingActiveEntities(/*int|array*/ $entity_restrict, ?array $active_entities, /*int|array*/ $result): void
+    {
+        $_SESSION['glpiactiveentities'] = $active_entities;
+        $this->variable(\Session::getMatchingActiveEntities($entity_restrict))->isEqualTo($result);
+    }
 }

Vulnerable code:     $_POST["entity_restrict"],
                    'entity'      => $_POST['entity_restrict'],
                    'entity'    => $_POST['entity_restrict'],
                    'entity'    => $_POST['entity_restrict'],
        'entity_restrict' => $_POST['entity_restrict'],
        ] + getEntitiesRestrictCriteria('glpi_softwarelicenses', 'entities_id', $_POST['entity_restrict'], true),
$opt = ['entity' => $_POST["entity_restrict"]];
        'entity_restrict'     => $_POST['entity_restrict'],
            'entity_restrict' => $_POST['entity_restrict'],
Item_Ticket::dropdownMyDevices($_POST["userID"], $_POST["entity_restrict"]);
                            $options['entity'] = $_POST['entity_restrict'];
            'entity' => $options['entities_id'] ?? $options['entity_restrict']
                                                              => $input["entities_id"],
        if (
            $post["entity_restrict"] = $entities;
        }
        if (isset($post['entity_restrict']) && 'default' === $post['entity_restrict']) {
            $post['entity_restrict'] = $_SESSION['glpiactiveentities'];
                $entity = $post["entity_restrict"];
            'entity_restrict'    => $p['entity'],
Fixed code: if (isset($_POST['entity_restrict'])) {
    $_POST['entity_restrict'] = Session::getMatchingActiveEntities($_POST['entity_restrict']);
}

    Session::getMatchingActiveEntities($_POST['entity_restrict']),
                    'entity'      => Session::getMatchingActiveEntities($_POST['entity_restrict']),
                    'entity'    => Session::getMatchingActiveEntities($_POST['entity_restrict']),
                    'entity'    => Session::getMatchingActiveEntities($_POST['entity_restrict']),
        'entity_restrict' => Session::getMatchingActiveEntities($_POST['entity_restrict']),
        ] + getEntitiesRestrictCriteria('glpi_softwarelicenses', 'entities_id', Session::getMatchingActiveEntities($_POST['entity_restrict']), true),
$opt = ['entity' => Session::getMatchingActiveEntities($_POST['entity_restrict'])];
        'entity_restrict'     => Session::getMatchingActiveEntities($_POST['entity_restrict']),
            'entity_restrict' => Session::getMatchingActiveEntities($_POST['entity_restrict']),
Item_Ticket::dropdownMyDevices($_POST["userID"], Session::getMatchingActiveEntities($_POST['entity_restrict']));
                            $options['entity'] = Session::getMatchingActiveEntities($_POST['entity_restrict']);
            'entity' => Session::getMatchingActiveEntities($options['entities_id'] ?? $options['entity_restrict']),
                                                              => Session::getMatchingActiveEntities($input["entities_id"]),
        $params['entity'] = Session::getMatchingActiveEntities($params['entity']);
        if (isset($post['entity_restrict']) && 'default' === $post['entity_restrict']) {
            $post['entity_restrict'] = $_SESSION['glpiactiveentities'];
        } elseif (
            $post["entity_restrict"] = Session::getMatchingActiveEntities($entities);
        if (isset($post['entity_restrict'])) {
            $post['entity_restrict'] = Session::getMatchingActiveEntities($post['entity_restrict']);
        }

                $entity = Session::getMatchingActiveEntities($post['entity_restrict']);
                $entity_restrict = Session::getMatchingActiveEntities($entity_restrict);
            $entity_restrict = Session::getMatchingActiveEntities($entity_restrict);
        $entity_restrict = Session::getMatchingActiveEntities($entity_restrict);

            'entity_restrict'    => Session::getMatchingActiveEntities($p['entity']),
    /**
     * Filter given entities ID list to return only these tht are matching current active entities in session.
     *
     * @since 10.0.13
     *
     * @param int|int[] $entities_ids
     *
     * @return int|int[]
     */
    public static function getMatchingActiveEntities(/*int|array*/ $entities_ids)/*: int|array*/
    {
        if (
            (int)$entities_ids === -1
            || (is_array($entities_ids) && count($entities_ids) === 1 && (int)reset($entities_ids) === -1)
        ) {
            // Special value that is generally used to fallback to all active entities.
            return $entities_ids;
        }

        if (!is_array($entities_ids) && !is_int($entities_ids) && !ctype_digit($entities_ids)) {
            // Unexpected value type.
            return [];
        }

        $active_entities_ids = $_SESSION['glpiactiveentities'] ?? [];

        if (!is_array($entities_ids) && in_array((int)$entities_ids, $active_entities_ids, true)) {
            return (int)$entities_ids;
        }

        $filtered = [];
        foreach ((array)$entities_ids as $entity_id) {
            if (
                (is_int($entity_id) || ctype_digit($entity_id))
                && in_array((int)$entity_id, $active_entities_ids, true)
            ) {
                $filtered[] = (int)$entity_id;
            }
        }
        return $filtered;
    }


        $p['entity'] = Session::getMatchingActiveEntities($p['entity']);

    protected function entitiesRestricProvider(): iterable
    {
        // Special case for -1
        foreach ([-1, "-1", [-1], ["-1"]] as $value) {
            yield [
                'entity_restrict' => $value,
                'active_entities' => [0, 1, 2, 3],
                'result'          => is_array($value) ? [-1] : -1,
            ];
        }

        // Integer input, matching
        yield [
            'entity_restrict' => 2,
            'active_entities' => [0, 1, 2, 3],
            'result'          => 2,
        ];

        // String input, matching
        yield [
            'entity_restrict' => '2',
            'active_entities' => [0, 1, 2, 3],
            'result'          => 2,
        ];

        // Integer input, NOT matching
        yield [
            'entity_restrict' => 7,
            'active_entities' => [0, 1, 2, 3],
            'result'          => [],
        ];

        // String input, matching
        yield [
            'entity_restrict' => '7',
            'active_entities' => [0, 1, 2, 3],
            'result'          => [],
        ];

        // Array input, ALL matching
        yield [
            'entity_restrict' => [0, '2', 3],
            'active_entities' => [0, 1, 2, 3],
            'result'          => [0, 2, 3],
        ];

        // Array input, PARTIAL matching
        yield [
            'entity_restrict' => [0, '2', 3, 12, 54, 96],
            'active_entities' => [0, 1, 2, 3],
            'result'          => [0, '2', 3],
        ];

        // Array input, NONE matching
        yield [
            'entity_restrict' => [0, '2', 3, 12, 54, 96],
            'active_entities' => [1, 4],
            'result'          => [],
        ];

        // Empty active entities
        yield [
            'entity_restrict' => [0, '2', 3, 12, 54, 96],
            'active_entities' => null,
            'result'          => [],
        ];

        // Unexpected unique value
        yield [
            'entity_restrict' => 'not a valid value',
            'active_entities' => [0, 1, 2, 3],
            'result'          => [],
        ];

        // Unexpected value in an array
        yield [
            'entity_restrict' => [0, 'not a valid value', 3],
            'active_entities' => [0, 1, 2, 3],
            'result'          => [0, 3],
        ];
    }

    /**
     * @dataProvider entitiesRestricProvider
     */
    public function testGetMatchingActiveEntities(/*int|array*/ $entity_restrict, ?array $active_entities, /*int|array*/ $result): void
    {
        $_SESSION['glpiactiveentities'] = $active_entities;
        $this->variable(\Session::getMatchingActiveEntities($entity_restrict))->isEqualTo($result);
    }