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

CVE-2026-41891

CVE-2026-41891

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.26.0 to before version 0.31.8.0, the auth filter has the deactivated/banned user check commented out. 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.26.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.