VYPR
Medium severityGHSA Advisory· Published May 7, 2026· Updated May 7, 2026

CVE-2026-41890

CVE-2026-41890

Description

CI4MS is a CodeIgniter 4-based CMS skeleton that delivers a production-ready, modular architecture with RBAC authorization and theme support. From version 0.31.1.0 to before version 0.31.8.0, 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 issue has been patched in version 0.31.8.0.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
ci4-cms-erp/ci4msPackagist
>= 0.31.1.0, < 0.31.8.00.31.8.0

Affected products

1

Patches

1
2f38284281ce

security:resolve arbitrary table drop and session bypass vulnerabilities

https://github.com/ci4-cms-erp/ci4msBertuğ Fahri ÖZERApr 18, 2026via ghsa
9 files changed · +67 38
  • CHANGELOG.md+8 0 modified
    @@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file.
     
     The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) conventions adapted to the existing four-component version numbers.
     
    +## [0.31.8.0] - 2026-04-19
    +
    +### Fixed
    +
    +- **Security (Session Management):** Re-activated user account status verification in `Ci4MsAuthFilter`. Deactivated or banned users now have their sessions immediately terminated upon their next request, remediating a session bypass flaw.
    +- **Security (Arbitrary Table Drop):** Implemented migration-based whitelist validation in `Theme::deleteProcess`. This ensures that selectively dropping database tables during theme deletion is restricted exclusively to tables declared within the specific theme's migration files, preventing arbitrary database table deletion.
    +
     ## [0.31.7.0] - 2026-04-17
     
     ### Added
    @@ -286,6 +293,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
     
     - Expanded database migrations and introduced new supporting libraries.
     
    +[0.31.8.0]: https://github.com/ci4-cms-erp/ci4ms/releases/tag/0.31.8.0
     [0.31.7.0]: https://github.com/ci4-cms-erp/ci4ms/releases/tag/0.31.7.0
     [0.31.6.0]: https://github.com/ci4-cms-erp/ci4ms/releases/tag/0.31.6.0
     [0.31.5.0]: https://github.com/ci4-cms-erp/ci4ms/releases/tag/0.31.5.0
    
  • composer.json+1 1 modified
    @@ -23,7 +23,7 @@
             "codeigniter4/translations": "4.7.0",
             "ezyang/htmlpurifier": "4.19",
             "gregwar/captcha": "1.3.0",
    -        "studio-42/elfinder": "2.1.66"
    +        "studio-42/elfinder": "2.1.67"
         },
         "require-dev": {
             "fakerphp/faker": "^1.9",
    
  • composer.lock+7 7 modified
    @@ -4,7 +4,7 @@
             "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
             "This file is @generated automatically"
         ],
    -    "content-hash": "d086c1578c2121d3653c4bb8d056ff9a",
    +    "content-hash": "eb2830c2098f60123c81540a89c34295",
         "packages": [
             {
                 "name": "bertugfahriozer/ci4commonmodel",
    @@ -840,16 +840,16 @@
             },
             {
                 "name": "studio-42/elfinder",
    -            "version": "2.1.66",
    +            "version": "2.1.67",
                 "source": {
                     "type": "git",
                     "url": "https://github.com/Studio-42/elFinder.git",
    -                "reference": "78488951e44d69e8b9e4e849f8268df408632a6c"
    +                "reference": "5e463d1384972dffcb736ad3c94f35af10656ca2"
                 },
                 "dist": {
                     "type": "zip",
    -                "url": "https://api.github.com/repos/Studio-42/elFinder/zipball/78488951e44d69e8b9e4e849f8268df408632a6c",
    -                "reference": "78488951e44d69e8b9e4e849f8268df408632a6c",
    +                "url": "https://api.github.com/repos/Studio-42/elFinder/zipball/5e463d1384972dffcb736ad3c94f35af10656ca2",
    +                "reference": "5e463d1384972dffcb736ad3c94f35af10656ca2",
                     "shasum": ""
                 },
                 "require": {
    @@ -896,15 +896,15 @@
                 "homepage": "http://elfinder.org",
                 "support": {
                     "issues": "https://github.com/Studio-42/elFinder/issues",
    -                "source": "https://github.com/Studio-42/elFinder/tree/2.1.66"
    +                "source": "https://github.com/Studio-42/elFinder/tree/2.1.67"
                 },
                 "funding": [
                     {
                         "url": "https://github.com/nao-pon",
                         "type": "github"
                     }
                 ],
    -            "time": "2025-08-28T11:51:22+00:00"
    +            "time": "2026-04-17T03:02:32+00:00"
             },
             {
                 "name": "symfony/finder",
    
  • .gitignore+0 15 modified
    @@ -135,31 +135,16 @@ template
     app/Config/Routes.php
     *.zip
     .history
    -.devilbox
    -htdocs
     public/uploads/.tmb/
     public/uploads/.trash/
     public/media/.tmb/
     writable/tmp/*
     bertug_s_docs
    -modules/Grapes
    -modules/ActivityLog
    -modules/Crm
    -modules/Cronjobs
    -modules/DocumentManager
    -modules/EmailManagement
    -modules/FormBuilder
    -modules/TaskManager
    -modules/LicenseServer
    -modules/LicenseClient
    -modules/TaskManager
    -public/be-assets/plugins/grapesjs
     .agent
     build/
     dist/
     composer.lock.json
     .antigravityignore
     .claude
    -modules/Notifications
     tests/*
     phpunit.xml.dist
    
  • modules/Auth/Filters/Ci4MsAuthFilter.php+4 4 modified
    @@ -13,12 +13,12 @@ public function before(RequestInterface $request, $arguments = null)
             if (! auth()->loggedIn()) {
                 return redirect()->route('login');
             }
    -        /* $user = auth()->user();
    -        if ($user && ($user->isBanned() || !$user->active)) {
    -            auth('session')->logout();
    +        $user = auth()->user();
     
    +        if ($user && ($user->isBanned() || (isset($user->active) && (int)$user->active === 0))) {
    +            auth('session')->logout();
                 return redirect()->route('login')->with('error', lang('Auth.bannedUser'));
    -        } */
    +        }
     
             $router = service('router');
             $controllerName = $router->controllerName();
    
  • modules/Backend/Commands/Ci4msSetup.php+1 1 modified
    @@ -218,7 +218,7 @@ public function run(array $params)
                 'app.supportedLocales'               => '["ar","de","en","es","fr","hi","ja","pt","ru","tr","zh"]',
                 'app.negotiateLocale'                => 'true',
                 'app.appTimezone'                    => '\'Europe/Istanbul\'',
    -            'app.version'                        => '0.31.7.0',
    +            'app.version'                        => '0.31.8.0',
             ];
     
             if (!$this->updateEnvSettings($updates)) {
    
  • modules/Install/Controllers/Install.php+1 1 modified
    @@ -66,7 +66,7 @@ public function index()
                     'app.supportedLocales' => '["ar","de","en","es","fr","hi","ja","pt","ru","tr","zh"]',
                     'app.negotiateLocale' => 'true',
                     'app.appTimezone' => '\'Europe/Istanbul\'',
    -                'app.version' => '0.31.7.0'
    +                'app.version' => '0.31.8.0'
                 ];
                 if ($this->copyEnvFile() && $this->updateEnvSettings($updates)) $this->generateEncryptionKey();
     
    
  • modules/Theme/Controllers/Theme.php+44 8 modified
    @@ -24,11 +24,32 @@ public function upload()
                 // Allowed static file extensions for the public/ directory.
                 // PHP files MUST NOT be written under public/ (RCE prevention).
                 $allowedPublicExtensions = [
    -                'css', 'js', 'map',
    -                'png', 'jpg', 'jpeg', 'gif', 'svg', 'webp', 'ico', 'bmp', 'avif',
    -                'woff', 'woff2', 'ttf', 'eot', 'otf',
    -                'xml', 'json', 'txt', 'md',
    -                'mp4', 'webm', 'ogg', 'mp3', 'wav',
    +                'css',
    +                'js',
    +                'map',
    +                'png',
    +                'jpg',
    +                'jpeg',
    +                'gif',
    +                'svg',
    +                'webp',
    +                'ico',
    +                'bmp',
    +                'avif',
    +                'woff',
    +                'woff2',
    +                'ttf',
    +                'eot',
    +                'otf',
    +                'xml',
    +                'json',
    +                'txt',
    +                'md',
    +                'mp4',
    +                'webm',
    +                'ogg',
    +                'mp3',
    +                'wav',
                     'pdf',
                 ];
     
    @@ -142,16 +163,31 @@ public function deleteProcess(string $slug)
                 return redirect()->route('templateSettings')->with('errors', [lang('Theme.themeActiveCannotDelete')]);
             }
     
    +        $allowedTables = [];
    +        $migrationPath = APPPATH . 'Database/Migrations/templates/' . $themeName;
    +        if (is_dir($migrationPath)) {
    +            $files = glob($migrationPath . '/*.php');
    +            foreach ($files as $file) {
    +                $content = file_get_contents($file);
    +                preg_match_all("/\\\$this->forge->createTable\s*\(\s*['\"]([^'\"]+)['\"]/i", $content, $matches);
    +                if (!empty($matches[1])) {
    +                    foreach ($matches[1] as $tName) {
    +                        $allowedTables[] = $tName;
    +                    }
    +                }
    +            }
    +        }
    +        $allowedTables = array_unique($allowedTables);
             $log = [];
    -        // Delete tables (selected ones)
             $tablesToDrop = $this->request->getPost('tables');
             if (!empty($tablesToDrop) && is_array($tablesToDrop)) {
                 $forge = \Config\Database::forge();
                 $db = \Config\Database::connect();
                 foreach ($tablesToDrop as $table) {
    -                if ($db->tableExists($table)) {
    +                // Sadece izin verilen (temaya ait) tabloları sil
    +                if (in_array($table, $allowedTables) && $db->tableExists($table)) {
                         $forge->dropTable($table, true);
    -                    $log[] = "🗑️ Table deleted: $table";
    +                    $log[] = "🗑️ " . lang('Theme.tableDeleted', [$table]);
                     }
                 }
             }
    
  • README.md+1 1 modified
    @@ -201,6 +201,6 @@ A huge thank you to the security researchers who have helped make **ci4ms** more
     | **[offset](https://github.com/offset)** | Identified Critical vulnerabilities including multiple Stored XSS, Authorization Bypass in Fileeditor, Install Guard Bypass, and CRLF Injection. | Apr 2026 |
     | **[fg0x0](https://github.com/fg0x0)** | Identified Critical Arbitrary File Write (Zip Slip RCE) vulnerabilities in Theme::upload and Backup::restore modules. | Apr 2026 |
     | **[0xAlchemist](https://github.com/bugmithlegend)** , **[peeefour](https://github.com/peeefour)** and **[DexterHK](https://github.com/DexterHK)** | Identified Critical Full Account Takeover and Privilege Escalation via Stored DOM Blind XSS in Backup Management (v2). | Apr 2026 |
    -| **[dapickle](https://github.com/dapickle)** | Identified Critical Authenticated Remote Code Execution (RCE) via unrestricted PHP file upload in Theme installation | Apr 2026 |
    +| **[dapickle](https://github.com/dapickle)** | Identified Critical Authenticated RCE in Theme installation, Arbitrary Database Table Drop in Theme module, and a Session Management Bypass. | Apr 2026 |
     
     > If you find a security vulnerability, please report it via [Security Policy](SECURITY.md).
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.