CVE-2026-41890: ci4-cms-erp/ci4ms · CI4MS Vulnerable to Arbitrary Database Table Drop via Theme deleteProcess
Affects ci4-cms-erp/ci4msSource GCVE Database
Not known to be exploited · CVSS 6.9 Medium : upgrade to 0.31.8.0 when convenient.
Data as of 27 Oct 2026, 00:07 UTC
- Patch
- Available – fixed in 0.31.8.0
CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:NExploitation evidence
Disclosed: evidence found.
CVE published 7 May 2026
Detectable: no evidence on record.
No public nuclei template indexed
Weaponised: no evidence on record.
No public exploit code indexed in Metasploit or Exploit-DB
Exploited in the wildExploited: no evidence on record.
Not in CISA KEV and no source reports exploitation
Observed by OffSeq MirageSeen by Mirage: no evidence on record.
No attack traffic recorded by OffSeq Mirage sensors
A missing step is not evidence of safety. Sources: cve.org (opens in a new tab), the Metasploit, Exploit-DB and nuclei-templates index as of 26 Oct 2026.
What to do
Upgrade ci4-cms-erp/ci4ms to 0.31.8.0.
Affected software
| Product | Affected | Fixed in |
|---|---|---|
| Packagistci4-cms-erp/ci4ms | Affected
| Fixed in
|
Check your own hosts for these packages with threat-finder (opens in a new tab), our free open-source scanner.
Description
### Summary The `deleteProcess()` action accepts a POST parameter `tables[]` containing arbitrary table names. These are passed directly to `$forge->dropTable()` without validating that the tables belong to the theme being deleted. The `deleteConfirm` view correctly populates `tables[]` from the theme's own migration files, but the server-side `deleteProcess` does not verify the received values against those files. An authenticated admin can craft a POST request with arbitrary table names and drop any table in the database. This is a real bug even within the admin trust model: the action should be scoped to the theme's own tables. The permission grants delete this theme's data", not "drop any table". ### Details ### Location `modules/Theme/Controllers/Theme.php` :: `deleteProcess()` ~line 147 ### Vulnerable Code ```php public function deleteProcess(string $slug) { $themeName = $slug; $activeTheme = setting('App.siteTheme'); if ($activeTheme === $themeName) { return redirect()->route('templateSettings')...; } $tablesToDrop = $this->request->getPost('tables'); // ← user-supplied, unvalidated if (!empty($tablesToDrop) && is_array($tablesToDrop)) { $forge = \Config\Database::forge(); $db = \Config\Database::connect(); foreach ($tablesToDrop as $table) { if ($db->tableExists($table)) { $forge->dropTable($table, true); // ← no whitelist check } } } ``` ### PoC 1. Authenticate to the backend (any user with theme.delete permission) 2. POST to `/backend/themes/delete-process/<any_non_active_theme_slug>` 3. Include `tables[]=<any_table>` in POST body 4. The named tables are dropped without validation ### Impact - Dropped `ci4ms_blog` (confirmed in test) - Dropped `ci4ms_users` + `ci4ms_auth_identities` simultaneously — disables all authentication (confirmed) - Any table in the database can be targeted ### Additional note Quick note on the design intent for deleteProcess — I noticed delete_confirm.php scopes the checkboxes to the theme's own migration files, and the CHANGELOG confirms the selective deletion was intentional (admins can choose which tables to keep). The server-side deleteProcess already has all the information it needs to validate the input — deleteConfirm derives the valid table set from the migration files, deleteProcess just needs to do the same before acting on the POST. Happy to clarify if useful.
References
- github.com/ci4-cms-erp/ci4ms/security/advisories/GHSA-vgrf-pr28-vf98 (opens in a new tab)
- nvd.nist.gov/vuln/detail/CVE-2026-41890 (opens in a new tab)
- github.com/ci4-cms-erp/ci4ms/commit/2f38284281ce6b435ea42003951f14109ac2cea7 (opens in a new tab)
- github.com/ci4-cms-erp/ci4ms (opens in a new tab)
- github.com/ci4-cms-erp/ci4ms/releases/tag/0.31.8.0 (opens in a new tab)