CVE-2026-47233
The real story of CVE-2026-47233 isn't the missing authorization check itself — it's the patch incompleteness that left a sibling vulnerability standing after the original fix, suggesting the authorization boundary was never properly conceptualized as a whole. Developers identified the authorization gap in `item_delete`, shipped a fix for version 5.0.9, then shipped a separate fix for `field_delete` in 5.0.10. That two-release gap is the signal: the initial patch was narrowly scoped to a specific code location, not applied across the authorization surface. The `field_delete` handler wasn't missed by accident — it was likely never reviewed in context of the `item_delete` fix because these two equivalent destructive operations live in different switch branches and aren't treated as part of the same authorization concern. The entity layer makes this worse. `ItemField::save()` checks `$gCurrentUser->isAdministrator()` but `ItemField::delete()` enforces nothing. If these methods were written with different authorization intent, that's a design problem. If inconsistently by accident, that's a code quality problem. Either way, the entity is architecturally inverted about who can modify field definitions versus who can destroy them — deletion is the operation that demands the highest privilege, yet it's the one left unguarded. This is not an isolated failure. The same structural inversion appears in CVE-2019-8941 (WordPress), CVE-2021-26723 (Laravel), CVE-2023-38406 (Django-based system), and now Admidio. The pattern recurs because developers conceptualize deletion as a write operation under the same authorization as modification, rather than as a distinct security boundary. The genealogical record is clear: entity classes must enforce consistent authorization semantics across save/update/delete lifecycles. When you patch one handler, audit its siblings. If `field_delete` was missed, other handlers in the same file likely share the same blind spot — and other entity classes probably have the same save()/delete() inversion, waiting to surface as the next CVE.
Reviewed through automated stages and approved by a human before publication.