GitHub Advisoryadvisory · Packagist
GHSA-vgrf-pr28-vf98 CI4MS Vulnerable to Arbitrary Database Table Drop via Theme deleteProcess
MEDIUM
Official page ↗
- Aliases
- CVE-2026-41890
- Ecosystem
- Packagist
- Packages
- ci4-cms-erp/ci4ms
- Severity
- Moderate
- CVSS vector
- CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
- Weaknesses
- CWE-20
- Reviewed
- 2026-05-04
Affected packages
• Packagist ci4-cms-erp/ci4ms: >= 0.31.1.0, < 0.31.8.0 → fixed in 0.31.8.0
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/`
3. Include `tables[]=` 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.
Related
Alias · CVE (1)
- CVE-2026-41890 CI4MS is a CodeIgniter 4-based CMS skeleton that delivers a production-ready, modular architecture with RBAC authorization and theme… vulnerability
Weakness · CWE (1)
- CWE-20 Improper Input Validation weakness
References
- https://github.com/ci4-cms-erp/ci4ms/security/advisories/GHSA-vgrf-pr28-vf98 web
- https://nvd.nist.gov/vuln/detail/CVE-2026-41890 advisory
- https://github.com/ci4-cms-erp/ci4ms/commit/2f38284281ce6b435ea42003951f14109ac2cea7 web
- https://github.com/ci4-cms-erp/ci4ms package
- https://github.com/ci4-cms-erp/ci4ms/releases/tag/0.31.8.0 web