{"id":"CVE-2026-41890","aliases":["GHSA-vgrf-pr28-vf98"],"url":"https://o3.security/vulnerability/CVE-2026-41890","summary":"CI4MS: Arbitrary Database Table Drop via Theme deleteProcess","details":"### Summary\nThe `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.\n\nThe `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.\n\nThis 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\".\n\n### Details\n\n### Location\n`modules/Theme/Controllers/Theme.php` :: `deleteProcess()` ~line 147\n\n### Vulnerable Code\n```php\npublic function deleteProcess(string $slug)\n{\n    $themeName = $slug;\n    $activeTheme = setting('App.siteTheme');\n    if ($activeTheme === $themeName) {\n        return redirect()->route('templateSettings')...;\n    }\n\n    $tablesToDrop = $this->request->getPost('tables');  // ← user-supplied, unvalidated\n    if (!empty($tablesToDrop) && is_array($tablesToDrop)) {\n        $forge = \\Config\\Database::forge();\n        $db    = \\Config\\Database::connect();\n        foreach ($tablesToDrop as $table) {\n            if ($db->tableExists($table)) {\n                $forge->dropTable($table, true);  // ← no whitelist check\n            }\n        }\n    }\n```\n\n### PoC\n1. Authenticate to the backend (any user with theme.delete permission)\n2. POST to `/backend/themes/delete-process/<any_non_active_theme_slug>`\n3. Include `tables[]=<any_table>` in POST body\n4. The named tables are dropped without validation\n\n### Impact\n- Dropped `ci4ms_blog` (confirmed in test)\n- Dropped `ci4ms_users` + `ci4ms_auth_identities` simultaneously — disables all authentication (confirmed)\n- Any table in the database can be targeted\n\n### Additional note\nQuick 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.","published":"2026-05-07T03:23:31.339Z","modified":"2026-08-12T03:51:31.592785590Z","cvss":null,"epss":{"score":0.00344,"percentile":0.26898,"asOf":"2026-08-24"},"cisaKev":null,"exploitsKnown":0,"affectedPackages":[{"ecosystem":"Packagist","name":"ci4-cms-erp/ci4ms","fixedVersion":"0.31.8.0"}],"fix":{"url":"https://github.com/ci4-cms-erp/ci4ms/commit/2f38284281ce6b435ea42003951f14109ac2cea7","label":"ci4-cms-erp/ci4ms@2f38284"},"references":[{"type":"WEB","url":"https://github.com/ci4-cms-erp/ci4ms/releases/tag/0.31.8.0"},{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/41xxx/CVE-2026-41890.json"},{"type":"ADVISORY","url":"https://github.com/ci4-cms-erp/ci4ms/security/advisories/GHSA-vgrf-pr28-vf98"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-41890"},{"type":"WEB","url":"https://github.com/ci4-cms-erp/ci4ms/commit/2f38284281ce6b435ea42003951f14109ac2cea7"},{"type":"PACKAGE","url":"https://github.com/ci4-cms-erp/ci4ms"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-08-12T03:51:31.592785590Z"}}