Every CVE Search/ Get API key

CVE-2026-47233

Admidio: Any logged-in user can delete inventory fields via `mode=field_delete` — incomplete fix of #2024

6.5 MediumFix available

Admidio is an open-source user management solution. Version 5.0.9 added a missing isAdministratorInventory() gate to case 'item_delete': in modules/inventory.php. The same fix was not applied to the sibling case 'field_delete': handler, which destroys an entire inventory field definition, cascading to every adm_inventory_item_data row that referenced that field and every adm_inventory_field_options entry. The handler validates only a session-bound CSRF token; there is no isAdministratorInventory() check at the controller level, and Admidio\Inventory\Entity\ItemField::delete() does not enforce one at the entity level either (unlike its sibling ItemField::save(), which does check $gCurrentUser->isAdministrator()). Any user who can log in to the site can permanently destroy a non-system inventory field by sending one POST. Version 5.0.10 provides an updated fix.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
Low
User interaction
None

What an attacker can affect

Confidentiality
None
Integrity
High
Availability
None

Exploit likelihood

0.31%Up 0.3 points since Jun 12, 2026
90%50%10%1%

What each source reports

CVE List Score used 6.5

Admidio: Any logged-in user can delete inventory fields via `mode=field_delete` — incomplete fix of #2024

Admidio is an open-source user management solution. Version 5.0.9 added a missing isAdministratorInventory() gate to case 'item_delete': in modules/inventory.php. The same fix was not applied to the sibling case 'field_delete': handler, which destroys an entire inventory field definition, cascading to every adm_inventory_item_data row that referenced that field and every adm_inventory_field_options entry. The handler validates only a session-bound CSRF token; there is no isAdministratorInventory() check at the controller level, and Admidio\Inventory\Entity\ItemField::delete() does not enforce one at the entity level either (unlike its sibling ItemField::save(), which does check $gCurrentUser->isAdministrator()). Any user who can log in to the site can permanently destroy a non-system inventory field by sending one POST. Version 5.0.10 provides an updated fix.

Record
CVE-2026-47233
CVSS 3.1
6.5 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N
Weakness
CWE-862, CWE-1281
Updated
2026-11-02
EUVDEUVD-2026-57214 6.5

Admidio is an open-source user management solution. Version 5.0.9 added a missing isAdministratorInventory() gate to case 'item_delete': in modules/inventory.php. The same fix was not applied to the sibling case 'field_delete': handler, which destroys an entire inventory field definition, cascading to every adm_inventory_item_data row that referenced that field and every adm_inventory_field_options entry. The handler validates only a session-bound CSRF token; there is no isAdministratorInventory() check at the controller level, and Admidio\Inventory\Entity\ItemField::delete() does not enforce one at the entity level either (unlike its sibling ItemField::save(), which does check $gCurrentUser->isAdministrator()). Any user who can log in to the site can permanently destroy a non-system inventory field by sending one POST. Version 5.0.10 provides an updated fix.

Record
EUVD-2026-57214
CVSS 3.1
6.5 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N
Updated
2026-11-02
GitHub AdvisoriesGHSA-xw54-c3mx-9pm3 6.5

Admidio: Any logged-in user can delete inventory fields via `mode=field_delete` — incomplete fix of #2024

Summary

Commit d37ca6b27b9674238e58491cf7ba292e66898f15 ("Delete item not check admin rights #2024", 2026-04-12) added a missing isAdministratorInventory() gate to case 'item_delete': in modules/inventory.php. The same fix was not applied to the sibling case 'field_delete': handler, which destroys an entire inventory field definition, cascading to every adm_inventory_item_data row that referenced that field and every adm_inventory_field_options entry. The handler validates only a session-bound CSRF token; there is no isAdministratorInventory() check at the controller level, and Admidio\Inventory\Entity\ItemField::delete() does not enforce one at the entity level either (unlike its sibling ItemField::save(), which does check $gCurrentUser->isAdministrator()). Any user who can log in to the site can permanently destroy a non-system inventory field by sending one POST.

Details

Vulnerable Code

modules/inventory.php mode dispatch at the top of the file:

// modules/inventory.php:64-72  (top-level rights gate)
if ($gSettingsManager->getInt('inventory_module_enabled') === 0) {
    throw new Exception('SYS_MODULE_DISABLED');
} elseif ($gSettingsManager->getInt('inventory_module_enabled') === 2 && !$gValidLogin
    || ($gSettingsManager->getInt('inventory_module_enabled') === 3 && !$gCurrentUser->isAdministratorInventory())
    || ($gSettingsManager->getInt('inventory_module_enabled') === 4 && !InventoryPresenter::isCurrentUserKeeper() && !$gCurrentUser->isAdministratorInventory())
    || ($gSettingsManager->getInt('inventory_module_enabled') === 5 && !$gCurrentUser->isAllowedToSeeInventory() && !$gCurrentUser->isAdministratorInventory())) {
    throw new Exception('SYS_NO_RIGHTS');
}

inventory_module_enabled=2 is the default value (install/db_scripts/preferences.php: 'inventory_module_enabled' => '2',). At this setting the only gate is $gValidLogin — any logged-in user reaches the switch.

modules/inventory.php:123-131 — field_delete only checks the session CSRF, not admin rights:

case 'field_delete':
    // check the CSRF token of the form against the session token
    SecurityUtils::validateCsrfToken($_POST['adm_csrf_token']);

    $itemFieldService = new ItemFieldService($gDb, $getinfUUID);
    $itemFieldService->delete();

    echo json_encode(array('status' => 'success', 'message' => $gL10n->get('SYS_INVENTORY_ITEMFIELD_DELETED')));
    break;

SecurityUtils::validateCsrfToken (src/Infrastructure/Utils/SecurityUtils.php) is a session-token compare:

public static function validateCsrfToken(string $csrfToken)
{
    global $gCurrentSession;
    if ($csrfToken !== $gCurrentSession->getCsrfToken()) {
        throw new Exception('Invalid or missing CSRF token!');
    }
}

The token is the session's CSRF token, which the actor's own session prints on every page (it appears in ?mode=field_list's response in the data-csrf JSON callback). So a non-admin attacker has it for free.

src/Inventory/Service/ItemFieldService.php:46-49 — the service just delegates:

public function delete(): bool
{
    return $this->itemFieldRessource->delete();
}

src/Inventory/Entity/ItemField.php:54-88 — the entity's delete() blocks system fields via inf_system==1 but otherwise has no isAdministrator() check:

public function delete(): bool
{
    global $gCurrentOrgId;

    if ($this->getValue('inf_system') == 1) {
        // System fields could not be deleted
        throw new Exception('Item fields with the flag "system" could not be deleted.');
    }

    $this->db->startTransaction();

    // close gap in sequence
    $sql = 'UPDATE ' . TBL_INVENTORY_FIELDS . ' SET inf_sequence = inf_sequence - 1 ...';
    $this->db->queryPrepared($sql, ...);

    // delete all data of this field in the item data table
    $sql = 'DELETE FROM ' . TBL_INVENTORY_ITEM_DATA . ' WHERE ind_inf_id = ? -- $infId';
    $this->db->queryPrepared($sql,…
Record
GHSA-xw54-c3mx-9pm3
CVSS 3.1
6.5 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N
Weakness
CWE-862, CWE-1281
Updated
2026-11-02
NVD 6.5

Admidio is an open-source user management solution. Version 5.0.9 added a missing isAdministratorInventory() gate to case 'item_delete': in modules/inventory.php. The same fix was not applied to the sibling case 'field_delete': handler, which destroys an entire inventory field definition, cascading to every adm_inventory_item_data row that referenced that field and every adm_inventory_field_options entry. The handler validates only a session-bound CSRF token; there is no isAdministratorInventory() check at the controller level, and Admidio\Inventory\Entity\ItemField::delete() does not enforce one at the entity level either (unlike its sibling ItemField::save(), which does check $gCurrentUser->isAdministrator()). Any user who can log in to the site can permanently destroy a non-system inventory field by sending one POST. Version 5.0.10 provides an updated fix.

Record
CVE-2026-47233
CVSS 3.1
6.5 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N
Weakness
CWE-862, CWE-1281
Updated
2026-11-02
OSV 6.5

Admidio: Any logged-in user can delete inventory fields via `mode=field_delete` — incomplete fix of #2024

Admidio is an open-source user management solution. Version 5.0.9 added a missing isAdministratorInventory() gate to case 'item_delete': in modules/inventory.php. The same fix was not applied to the sibling case 'field_delete': handler, which destroys an entire inventory field definition, cascading to every adm_inventory_item_data row that referenced that field and every adm_inventory_field_options entry. The handler validates only a session-bound CSRF token; there is no isAdministratorInventory() check at the controller level, and Admidio\Inventory\Entity\ItemField::delete() does not enforce one at the entity level either (unlike its sibling ItemField::save(), which does check $gCurrentUser->isAdministrator()). Any user who can log in to the site can permanently destroy a non-system inventory field by sending one POST. Version 5.0.10 provides an updated fix.

Record
CVE-2026-47233
CVSS 3.1
6.5 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N
Weakness
CWE-1281, CWE-862
Updated
2026-11-02
OSVGHSA-xw54-c3mx-9pm3 6.5

Admidio: Any logged-in user can delete inventory fields via `mode=field_delete` — incomplete fix of #2024

Summary

Commit d37ca6b27b9674238e58491cf7ba292e66898f15 ("Delete item not check admin rights #2024", 2026-04-12) added a missing isAdministratorInventory() gate to case 'item_delete': in modules/inventory.php. The same fix was not applied to the sibling case 'field_delete': handler, which destroys an entire inventory field definition, cascading to every adm_inventory_item_data row that referenced that field and every adm_inventory_field_options entry. The handler validates only a session-bound CSRF token; there is no isAdministratorInventory() check at the controller level, and Admidio\Inventory\Entity\ItemField::delete() does not enforce one at the entity level either (unlike its sibling ItemField::save(), which does check $gCurrentUser->isAdministrator()). Any user who can log in to the site can permanently destroy a non-system inventory field by sending one POST.

Details

Vulnerable Code

modules/inventory.php mode dispatch at the top of the file:

// modules/inventory.php:64-72  (top-level rights gate)
if ($gSettingsManager->getInt('inventory_module_enabled') === 0) {
    throw new Exception('SYS_MODULE_DISABLED');
} elseif ($gSettingsManager->getInt('inventory_module_enabled') === 2 && !$gValidLogin
    || ($gSettingsManager->getInt('inventory_module_enabled') === 3 && !$gCurrentUser->isAdministratorInventory())
    || ($gSettingsManager->getInt('inventory_module_enabled') === 4 && !InventoryPresenter::isCurrentUserKeeper() && !$gCurrentUser->isAdministratorInventory())
    || ($gSettingsManager->getInt('inventory_module_enabled') === 5 && !$gCurrentUser->isAllowedToSeeInventory() && !$gCurrentUser->isAdministratorInventory())) {
    throw new Exception('SYS_NO_RIGHTS');
}

inventory_module_enabled=2 is the default value (install/db_scripts/preferences.php: 'inventory_module_enabled' => '2',). At this setting the only gate is $gValidLogin — any logged-in user reaches the switch.

modules/inventory.php:123-131 — field_delete only checks the session CSRF, not admin rights:

case 'field_delete':
    // check the CSRF token of the form against the session token
    SecurityUtils::validateCsrfToken($_POST['adm_csrf_token']);

    $itemFieldService = new ItemFieldService($gDb, $getinfUUID);
    $itemFieldService->delete();

    echo json_encode(array('status' => 'success', 'message' => $gL10n->get('SYS_INVENTORY_ITEMFIELD_DELETED')));
    break;

SecurityUtils::validateCsrfToken (src/Infrastructure/Utils/SecurityUtils.php) is a session-token compare:

public static function validateCsrfToken(string $csrfToken)
{
    global $gCurrentSession;
    if ($csrfToken !== $gCurrentSession->getCsrfToken()) {
        throw new Exception('Invalid or missing CSRF token!');
    }
}

The token is the session's CSRF token, which the actor's own session prints on every page (it appears in ?mode=field_list's response in the data-csrf JSON callback). So a non-admin attacker has it for free.

src/Inventory/Service/ItemFieldService.php:46-49 — the service just delegates:

public function delete(): bool
{
    return $this->itemFieldRessource->delete();
}

src/Inventory/Entity/ItemField.php:54-88 — the entity's delete() blocks system fields via inf_system==1 but otherwise has no isAdministrator() check:

public function delete(): bool
{
    global $gCurrentOrgId;

    if ($this->getValue('inf_system') == 1) {
        // System fields could not be deleted
        throw new Exception('Item fields with the flag "system" could not be deleted.');
    }

    $this->db->startTransaction();

    // close gap in sequence
    $sql = 'UPDATE ' . TBL_INVENTORY_FIELDS . ' SET inf_sequence = inf_sequence - 1 ...';
    $this->db->queryPrepared($sql, ...);

    // delete all data of this field in the item data table
    $sql = 'DELETE FROM ' . TBL_INVENTORY_ITEM_DATA . ' WHERE ind_inf_id = ? -- $infId';
    $this->db->queryPrepared($sql,…
Record
GHSA-xw54-c3mx-9pm3
CVSS 3.1
6.5 MediumCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N
Weakness
CWE-1281, CWE-862
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
admidio/admidio
Packagist
through 5.0.9
5.0.10
admidio/admidio
Packagist
before 5.0.10, plus listed versions
4.1.04.1.3v4.2-Beta.1v4.2-Beta.2v4.2-Beta.3
Show 45 moreShow less
v4.2.0v4.2.1v4.2.10v4.2.11v4.2.12v4.2.13v4.2.14v4.2.2v4.2.3v4.2.4v4.2.5v4.2.6v4.2.7v4.2.8v4.2.9v4.3-Beta.1v4.3-Beta.3v4.3-Beta.4v4.3-Beta.5v4.3.0v4.3.1v4.3.10v4.3.11v4.3.12v4.3.13v4.3.14v4.3.15v4.3.16v4.3.17v4.3.2v4.3.3v4.3.4v4.3.5v4.3.6v4.3.7v4.3.8v4.3.9v5.0-Beta.1v5.0-Beta.2v5.0-Beta.3v5.0.0v5.0.1v5.0.2v5.0.3v5.0.4
5.0.10

History

History
RecordedChangedSources
aliasesEUVD
first indexedCVE List, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-47233 is a medium vulnerability (CVSS 6.5) in Admidio, published May 29, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.31%, the 24th percentile. Fixed in admidio/admidio 5.0.10.

References

This page doesn't list everything

Left out here: 5 versions and the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open