VYPR
High severityNVD Advisory· Published Jun 3, 2026

CVE-2026-42318

CVE-2026-42318

Description

GLPI versions 9.5.0 through 11.0.6 allow low-privilege users to delete any object via the planning feature.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

GLPI versions 9.5.0 through 11.0.6 allow low-privilege users to delete any object via the planning feature.

Vulnerability

GLPI versions 9.5.0 and prior to 10.0.25 and 11.0.7 contain a vulnerability that allows low-privilege users with access to the planning feature to delete any object within the application. This issue affects the planning module of the software.

Exploitation

An attacker with low-privilege user access and permissions to the planning feature can exploit this vulnerability. The attacker needs to interact with the planning interface to initiate the deletion of any object within GLPI.

Impact

Successful exploitation allows an attacker to delete any object in GLPI, leading to data loss and potential disruption of IT management functions. The scope of the compromise is limited to the data within the GLPI instance that the attacker can access via the planning feature.

Mitigation

Upgrade to GLPI version 11.0.7 or 10.0.25 to receive a patch. As a workaround, disable delete rights for User's planning. The fixed versions were released on 2024-05-23 [1].

AI Insight generated on Jun 3, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

2
  • Glpi Project/Glpiinferred2 versions
    >=9.5.0,<11.0.7+ 1 more
    • (no CPE)range: >=9.5.0,<11.0.7
    • (no CPE)range: >=9.5.0, <10.0.25, <11.0.7

Patches

3
ac57d2f17727

Encrypt API session tokens (#23809)

https://github.com/glpi-project/glpiCédric AnneApr 9, 2026Fixed in 10.0.25via llm-release-walk
3 files changed · +12 2
  • src/Api/API.php+4 1 modified
    @@ -336,9 +336,12 @@ protected function initSession($params = [])
                 $this->returnError($error_msg, 401, $error_code, false);
             }
     
    +        $session_token = \base64_encode((new GLPIKey())->encrypt($_SESSION['valid_id']));
    +        unset($_SESSION['valid_id']); // this is not needed for the API, unsetting it prevents any unexpected exposure
    +
             // stop session and return session key
             session_write_close();
    -        $data = ['session_token' => $_SESSION['valid_id']];
    +        $data = ['session_token' => $session_token];
     
             // Insert session data if requested
             $get_full_session = $params['get_full_session'] ?? false;
    
  • src/Api/APIRest.php+2 1 modified
    @@ -40,6 +40,7 @@
     namespace Glpi\Api;
     
     use AllAssets;
    +use GLPIKey;
     use GLPIUploadHandler;
     use stdClass;
     use Toolbox;
    @@ -601,7 +602,7 @@ public function parseIncomingParams($is_inline_doc = false)
     
             // try to retrieve session_token in header
             if (isset($headers['Session-Token'])) {
    -            $parameters['session_token'] = $headers['Session-Token'];
    +            $parameters['session_token'] = (new GLPIKey())->decrypt(\base64_decode(trim($headers['Session-Token'])));
             }
     
             // try to retrieve app_token in header
    
  • src/Api/APIXmlrpc.php+6 0 modified
    @@ -35,6 +35,7 @@
     
     namespace Glpi\Api;
     
    +use GLPIKey;
     use Toolbox;
     
     class APIXmlrpc extends API
    @@ -269,6 +270,11 @@ public function parseIncomingParams()
                               ? $parameters[0]
                               : []);
     
    +        // decrypt session token
    +        if (\array_key_exists('session_token', $this->parameters)) {
    +            $this->parameters['session_token'] = (new GLPIKey())->decrypt(\base64_decode($this->parameters['session_token']));
    +        }
    +
             // transform input from array to object
             if (
                 isset($this->parameters['input'])
    
e035590cb691

Prevent conflicts between legacy API auth methods (#23811)

https://github.com/glpi-project/glpiCédric AnneApr 9, 2026Fixed in 10.0.25via llm-release-walk
3 files changed · +137 54
  • apirest.md+4 0 modified
    @@ -1748,6 +1748,10 @@ One of theses parameter(s) is missing:
     The GLPI setup forbid the login with credentials, you must login with your user_token instead.
     See your personal preferences page or setup API access in GLPI main interface.
     
    +### ERROR_LOGIN_WITH_TOKEN_DISABLED
    +
    +The GLPI setup forbid the login with user token, you must login with your login/password instead.
    +
     ### ERROR_GLPI_LOGIN_USER_TOKEN
     
     The provided user_token seems invalid.
    
  • phpunit/APIBaseClass.php+74 14 modified
    @@ -52,13 +52,6 @@ public function setUp(): void
             global $GLPI_CACHE;
             $GLPI_CACHE->clear();
     
    -        $this->initSessionCredentials();
    -    }
    -
    -    abstract public function initSessionCredentials();
    -
    -    public static function setUpBeforeClass(): void
    -    {
             // To bypass various right checks
             // This is mandatory to create/update/delete some items during tests.
             $_SESSION['glpishowallentities'] = 1;
    @@ -70,15 +63,20 @@ public static function setUpBeforeClass(): void
             $_SESSION['glpicronuserrunning'] = "cron_phpunit";
     
             // enable api config
    -        $config = new Config();
    -        $config->update([
    -            'id'                              => 1,
    -            'enable_api'                      => true,
    -            'enable_api_login_credentials'    => true,
    -            'enable_api_login_external_token' => true,
    -        ]);
    +        Config::setConfigurationValues(
    +            'core',
    +            [
    +                'enable_api'                      => true,
    +                'enable_api_login_credentials'    => true,
    +                'enable_api_login_external_token' => true,
    +            ]
    +        );
    +
    +        $this->initSessionCredentials();
         }
     
    +    abstract public function initSessionCredentials();
    +
         /**
          * @tags   api
          * @covers API::initSession
    @@ -99,6 +97,68 @@ public function testInitSessionUserToken()
             $this->assertArrayHasKey('session_token', $data);
         }
     
    +    /**
    +     * @tags   api
    +     * @covers API::initSession
    +     */
    +    public function testInitSessionUserTokenFailIfNotEnabled()
    +    {
    +        Config::setConfigurationValues(
    +            'core',
    +            [
    +                'enable_api_login_external_token' => false,
    +            ]
    +        );
    +
    +        $user = new User();
    +        $uid = getItemByTypeName('User', TU_USER, true);
    +        $this->assertTrue($user->getFromDB($uid));
    +        $token = $user->getAuthToken('api_token');
    +
    +        $this->query(
    +            'initSession',
    +            ['query' => ['user_token' => $token]],
    +            400,
    +            'ERROR_LOGIN_WITH_TOKEN_DISABLED'
    +        );
    +    }
    +
    +    /**
    +     * @tags   api
    +     * @covers API::initSession
    +     */
    +    public function testInitSessionCredentialsFailIfNotEnabled()
    +    {
    +        Config::setConfigurationValues(
    +            'core',
    +            [
    +                'enable_api_login_credentials' => false,
    +            ]
    +        );
    +
    +        $this->query(
    +            'initSession',
    +            ['query' => ['login' => TU_USER, 'password' => TU_PASS]],
    +            400,
    +            'ERROR_LOGIN_WITH_CREDENTIALS_DISABLED'
    +        );
    +    }
    +
    +    /**
    +     * @tags   api
    +     * @covers API::initSession
    +     */
    +    public function testInitSessionFallbackToCredentials()
    +    {
    +        $data = $this->query(
    +            'initSession',
    +            ['query' => ['user_token' => 'notvalid', 'login' => TU_USER, 'password' => TU_PASS]],
    +        );
    +
    +        $this->assertNotFalse($data);
    +        $this->assertArrayHasKey('session_token', $data);
    +    }
    +
         /**
          * @tags   api
          * @covers API::initSession
    
  • src/Api/API.php+59 40 modified
    @@ -263,58 +263,77 @@ protected function initSession($params = [])
             $this->checkAppToken();
             $this->logEndpointUsage(__FUNCTION__);
     
    -        if (
    -            (!isset($params['login'])
    -            || empty($params['login'])
    -            || !isset($params['password'])
    -            || empty($params['password']))
    -            && (!isset($params['user_token'])
    -             || empty($params['user_token']))
    -        ) {
    +        $login    = $params['login'] ?? '';
    +        $password = $params['password'] ?? '';
    +        $token    = $params['user_token'] ?? '';
    +
    +        if (($login !== '' || $password !== '') && !$CFG_GLPI['enable_api_login_credentials']) {
                 $this->returnError(
    -                __("parameter(s) login, password or user_token are missing"),
    +                __("usage of initSession resource with credentials is disabled"),
                     400,
    -                "ERROR_LOGIN_PARAMETERS_MISSING"
    +                "ERROR_LOGIN_WITH_CREDENTIALS_DISABLED",
    +                false
                 );
             }
    -
    -        $auth = new Auth();
    -
    -        // fill missing params (in case of user_token)
    -        if (!isset($params['login'])) {
    -            $params['login'] = '';
    -        }
    -        if (!isset($params['password'])) {
    -            $params['password'] = '';
    -        }
    -
    -        $noAuto = true;
    -        if (isset($params['user_token']) && !empty($params['user_token'])) {
    -            $_REQUEST['user_token'] = Sanitizer::dbEscape($params['user_token']);
    -            $noAuto = false;
    -        } elseif (!$CFG_GLPI['enable_api_login_credentials']) {
    +        if ($token !== '' && !$CFG_GLPI['enable_api_login_external_token']) {
                 $this->returnError(
    -                __("usage of initSession resource with credentials is disabled"),
    +                __("usage of initSession resource with user token is disabled"),
                     400,
    -                "ERROR_LOGIN_WITH_CREDENTIALS_DISABLED",
    +                "ERROR_LOGIN_WITH_TOKEN_DISABLED",
                     false
                 );
             }
     
    -        if (!isset($params['auth'])) {
    -            $params['auth'] = '';
    +        if (
    +            (!$CFG_GLPI['enable_api_login_credentials'] || $login === '' || $password === '')
    +            && (!$CFG_GLPI['enable_api_login_external_token'] || $token === '')
    +        ) {
    +            if ($CFG_GLPI['enable_api_login_credentials'] && $CFG_GLPI['enable_api_login_external_token']) {
    +                $this->returnError(
    +                    __("parameter(s) login, password or user_token are missing"),
    +                    400,
    +                    "ERROR_LOGIN_PARAMETERS_MISSING"
    +                );
    +            } elseif ($CFG_GLPI['enable_api_login_credentials']) {
    +                $this->returnError(
    +                    __("parameter(s) login, password are missing"),
    +                    400,
    +                    "ERROR_LOGIN_PARAMETERS_MISSING"
    +                );
    +            } else {
    +                $this->returnError(
    +                    __("parameter user_token is missing"),
    +                    400,
    +                    "ERROR_LOGIN_PARAMETERS_MISSING"
    +                );
    +            }
             }
     
    -        // login on glpi
    -        if (!$auth->login($params['login'], $params['password'], $noAuto, false, $params['auth'])) {
    -            $err = implode(' ', $auth->getErrors());
    -            if (
    -                isset($params['user_token'])
    -                && !empty($params['user_token'])
    -            ) {
    -                $this->returnError(__("parameter user_token seems invalid"), 401, "ERROR_GLPI_LOGIN_USER_TOKEN", false);
    -            }
    -            $this->returnError($err, 401, "ERROR_GLPI_LOGIN", false);
    +        $authenticated  = false;
    +        $error_msg      = '';
    +        $error_code     = '';
    +        $use_token_auth = $CFG_GLPI['enable_api_login_external_token'] && $token !== '';
    +        $use_login_auth = $CFG_GLPI['enable_api_login_credentials'] && $login !== '' && $password !== '';
    +
    +        if ($use_token_auth) {
    +            $_REQUEST['user_token'] = $token;
    +
    +            $auth = new Auth();
    +            $authenticated = $auth->login('', '', false, false, $params['auth'] ?? '');
    +            $error_code    = 'ERROR_GLPI_LOGIN_USER_TOKEN';
    +            $error_msg     = __("parameter user_token seems invalid");
    +        }
    +        if (!$authenticated && $use_login_auth) {
    +            unset($_REQUEST['user_token']);
    +
    +            $auth = new Auth();
    +            $authenticated = $auth->login($login, $password, true, false, $params['auth'] ?? '');
    +            $error_code    = 'ERROR_GLPI_LOGIN';
    +            $error_msg     = implode(' ', $auth->getErrors());
    +        }
    +
    +        if (!$authenticated) {
    +            $this->returnError($error_msg, 401, $error_code, false);
             }
     
             // stop session and return session key
    
0ea900cb51a3

Bump version

https://github.com/glpi-project/glpiJohan CwiklinskiApr 29, 2026Fixed in 11.0.7via release-tag
1 file changed · +1 1
  • src/autoload/constants.php+1 1 modified
    @@ -40,7 +40,7 @@
     define('GLPI_ROOT', dirname(__DIR__, 2));
     
     // Current version of GLPI
    -define('GLPI_VERSION', '11.0.7-dev');
    +define('GLPI_VERSION', '11.0.7');
     
     $schema_file = sprintf('%s/install/mysql/glpi-empty.sql', GLPI_ROOT);
     define(
    

Vulnerability mechanics

Root cause

"The API session token handling did not properly validate or decrypt session tokens, allowing unauthorized actions."

Attack vector

A low-privilege user with access to the planning module can exploit this vulnerability. By manipulating API requests, they can bypass intended authorization checks. This allows them to perform actions, such as deleting any object within GLPI, that they should not have permission to execute. The vulnerability is present in versions prior to 10.0.25 and 11.0.7 [patch_id=4683553].

Affected code

The vulnerability lies within the API handling code, specifically in `src/Api/APIXmlrpc.php` and `src/Api/APIRest.php`, where session tokens are processed. The changes in `src/Api/API.php` also address the authentication flow for API requests [patch_id=4683553, patch_id=4683554].

What the fix does

The patch introduces encryption and decryption for API session tokens using a GLPI key [patch_id=4683553]. This ensures that only valid and properly authenticated session tokens can be used to interact with the API. Additionally, the patch refactors API authentication logic to prevent conflicts and enforce configuration settings for login credentials and user tokens [patch_id=4683554].

Preconditions

  • authThe attacker must be a low-privilege user with access to the planning module.

Generated on Jun 3, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

1

News mentions

0

No linked articles in our index yet.