Skip to content

CVE-2026-23698: Verified Repro With Script Download

CVE-2026-23698: Vtiger CRM through 8.4.0 allows authenticated admin users to achieve remote code execution by uploading a crafted module ZIP that places PHP files in the web-accessible modules/ directory.

CVE-2026-23698 is verified against Vtiger CRM · other. Affected versions: through 8.4.0. Vulnerability class: RCE. This high reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00273.

REPRO-2026-00273 Vtiger CRM · other RCE Variant found Jul 8, 2026 CVE entry ↗ .txt
Severity
HIGH
CVSS
8.6
Confidence
HIGH
Reproduced in
33m 54s
Tool calls
237
Spend
$3.40
01 · Overview

What Is CVE-2026-23698?

CVE-2026-23698 is a high-severity (CVSS 8.6) authenticated remote code execution vulnerability in Vtiger CRM through 8.4.0. An admin user can upload a crafted module ZIP through the Module Manager import feature to place PHP files in the web-accessible modules/ directory. Pruva reproduced it (reproduction REPRO-2026-00273).

02 · Severity & CVSS

CVE-2026-23698 Severity & CVSS Score

CVE-2026-23698 is rated high severity, with a CVSS base score of 8.6 out of 10.

HIGH threat level
8.6 / 10 CVSS base
03 · Affected Versions

Affected Vtiger CRM Versions

Vtiger CRM · other versions through 8.4.0 are affected.

How to Reproduce CVE-2026-23698

$ pruva-verify REPRO-2026-00273
or curl -O https://pruva.dev/api/v1/reproductions/REPRO-2026-00273/artifacts/bundle/repro/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh
Run in a VM or disposable container. This exploits a real vulnerability.
06 · Proof of Reproduction

Proof of Reproduction for CVE-2026-23698

Remote code execution — reproduced
  • reached the target end-to-end
  • full exploit chain demonstrated
  • on the real production code path
  • high confidence
  • the upstream fix blocks the same trigger
Trigger

crafted module ZIP containing a valid manifest.xml and a PHP shell file

Attack chain
  1. Module Manager Import Module endpoint (index.php?module=ModuleManager&parent=Settings&view=ModuleImport&mode=importUserModuleStep1)
  2. install
  3. /modules/<module>/shell.php
Variants tested

Vtiger CRM 8.4.0 Module Manager Import also allows RCE via language-pack and layout-pack ZIPs, sharing the same web-root extraction root cause; the layout path has a bypassable PHP content filter.

How the agent worked 625 events · 237 tool calls · 34 min
34 minDuration
237Tool calls
191Reasoning steps
625Events
1Dead-ends
Agent activity over 34 min
Support
22
Hypothesis
2
Repro
381
Judge
21
Variant
195
0:0033:54

Root Cause and Exploit Chain for CVE-2026-23698

Versions: through 8.4.0 (tested on 8.4.0; the Module Manager import code path exists across the 8.x line)

Vtiger CRM 8.4.0 (and earlier 8.x versions) allows an authenticated administrator to upload a crafted module ZIP archive through the Module Manager → Import Module endpoint. The upload handler accepts any ZIP that contains a valid manifest.xml, and the installer extracts the entire archive under the web-root modules/ directory. Because there is no file-type/content validation, an attacker can include an executable PHP file in the ZIP. Once extracted, the PHP file is reachable directly via the web server (e.g. /modules/<moduleName>/shell.php) and executes outside of Vtiger’s routing/authentication layer, giving the attacker a persistent web shell and arbitrary remote code execution.

  • Product/component: Vtiger CRM (open-source PHP/MySQL CRM)
  • Affected versions: through 8.4.0 (tested on 8.4.0; the Module Manager import code path exists across the 8.x line)
  • Risk level: High
  • Consequences: A low-privilege administrator with access to the Module Manager can install arbitrary PHP into the web root, bypassing the application’s authentication/authorization boundary and achieving persistent, unauthenticated remote code execution as the web-server user (www-data).

Impact Parity

  • Disclosed/claimed maximum impact: Authenticated remote code execution via a crafted module ZIP (code execution).
  • Reproduced impact from this run: The reproduction script logged into the real Vtiger 8.4.0 application, uploaded a malicious ZIP through the Module Manager endpoint, completed the import, and then accessed http://localhost/modules/<module>/shell.php?cmd=whoami. The response contained the marker PRUVA_SHELL_OK and the output www-data, demonstrating that attacker-controlled PHP was executed.
  • Parity: full — the reproduced impact matches the claimed RCE impact.
  • Not demonstrated: None.

Root Cause

The vulnerability is in the Module Manager import workflow:

  1. Upload (modules/Settings/ModuleManager/views/ModuleImport.php::importUserModuleStep2) saves the uploaded ZIP to test/vtlib/ and only validates that manifest.xml exists and declares a valid module name and Vtiger version compatibility. It does not inspect the file list or file extensions inside the ZIP.
  2. Installation (modules/Settings/ModuleManager/actions/Basic.php::importUserModuleStep3) calls Vtiger_Package::import() on the saved ZIP, which extracts all contents under the web root, including modules/<ModuleName>/ and languages/en_us/.
  3. Direct execution: Apache resolves /modules/<ModuleName>/shell.php directly, invoking the PHP interpreter before Vtiger’s index.php routing or authentication checks. Any PHP file placed in the ZIP is therefore executable by anyone who knows its URL.

The architectural gap is that Vtiger treats modules/ as both an application-code directory and an import target, with no allowlist of file types or relocation of uploaded module contents outside the web root. The ticket/advisory notes that the only validation is the manifest XML, satisfying the file-type check for CWE-434.

Fix commit: The advisory lists patched versions as unknown, and no specific fix commit was supplied. The remediation should add a content-type/allowlist check before extraction (e.g., only .php, .tpl, .js, .css, .xml, .png, .jpg, etc., and reject PHP files that are not legitimate module class files, or move extracted modules outside the web root and route them through Vtiger’s authenticated front controller).

Reproduction Steps

The full, automated reproduction is in bundle/repro/reproduction_steps.sh. At a high level it:

  1. Installs PHP 8.5, MariaDB, Apache, and Python tools in the sandbox.
  2. Downloads Vtiger CRM 8.4.0 from SourceForge and deploys it to /var/www/html.
  3. Creates a fresh MariaDB database and user, then runs the Vtiger web installer automatically.
  4. Logs in as the admin user and completes the first-time System/User setup.
  5. Builds a malicious ZIP with a valid manifest.xml, a boilerplate language file, and modules/<module>/shell.php.
  6. Navigates to Module Manager → Import Module, uploads the ZIP, and completes the import.
  7. Accesses the extracted PHP file directly via HTTP with ?cmd=whoami and captures the output.

Expected evidence of reproduction: The webshell responds with the marker PRUVA_SHELL_OK and the output of the injected command (e.g., www-data).

Evidence

  • bundle/logs/reproduction_steps.log — full setup, install, and exploit trace.
  • bundle/repro/proof.log — captured webshell output for the last run.
  • bundle/repro/runtime_manifest.json — runtime evidence manifest (services, proof artifacts, endpoint).
  • bundle/artifacts/malmod_<module>/malmod.zip — the crafted module ZIP used in the successful run.

Key excerpt from bundle/repro/proof.log (second run):

PRUVA_SHELL_OK
www-data
www-data

Key excerpt from bundle/logs/reproduction_steps.log showing the install response and trigger:

[+] Upload accepted: file=usermodule_1783465710.zip name=ModSiUWLcoD type=module
[*] Installing the module
[+] Install response: {"success":true,"result":{"success":true,"importModuleName":"ModSiUWLcoD"}}
[*] Triggering webshell: http://localhost/modules/ModSiUWLcoD/shell.php?cmd=whoami
[+] Webshell output: 200 PRUVA_SHELL_OK
www-data
www-data

Environment captured during the run:

  • Vtiger CRM 8.4.0 (tarball from SourceForge)
  • Apache 2.4.66 + PHP 8.5 (mod_php)
  • MariaDB 11.8.6
  • Ubuntu 26.04 (resolute)

Recommendations / Next Steps

  • Immediate fix: Before calling Vtiger_Package::import(), enumerate the ZIP contents and reject the archive if it contains any file outside a strict allowlist of module file types (e.g., legitimate PHP class/ action/ view files, templates, language files, assets). In particular, reject arbitrary PHP files that do not belong to the module’s expected class hierarchy.
  • Architectural fix: Do not extract user-supplied module archives directly into the web-root modules/ directory. Instead, stage them outside the document root and only copy validated files into the application tree, or serve module assets through a non-executable endpoint.
  • Upgrade guidance: Until an official patch is released, restrict admin access and monitor the test/vtlib/ and modules/ directories for unexpected PHP files.
  • Testing: Add a regression test that uploads a ZIP containing a manifest.xml plus an arbitrary PHP file and asserts that the import is rejected and the PHP file is never created under modules/.

Additional Notes

  • Idempotency: The reproduction script was run twice consecutively in the same environment and succeeded both times. Each run uses a fresh database and a unique module name to avoid collisions with previously imported modules, so it is safe to run repeatedly.
  • Limitations: The reproduction requires the Vtiger 8.4.0 installer to create the database schema, which is a synchronous, long-running operation; the script waits up to 10 minutes for the installer to complete.
  • No sanitizer: The primary proof was produced against the real product without ASAN/UBSAN; the success oracle is the actual webshell response.

Variant Analysis & Alternative Triggers for CVE-2026-23698

Versions: through 8.4.0 (tested on the 8.4.0 SourceForge release tarball)

Vtiger CRM 8.4.0's authenticated admin Module Manager → Import feature is not only exploitable by uploading a malicious module ZIP (the original CVE-2026-23696 proof of concept), but also by uploading a language pack ZIP or a layout/theme ZIP through the same endpoint. Both alternate paths extract attacker-controlled PHP files into the web root without adequate validation. The language import path performs no content validation at all; the layout import path attempts a regex-based PHP detection that is bypassed by the PHP short-echo tag <?=. In both cases, the extracted PHP file is reachable directly via HTTP and executes as the web-server user, producing the same persistent, unauthenticated RCE outcome as the original module-import vulnerability. No vendor patch is available, so a true bypass of a fixed version could not be demonstrated; the confirmed findings are alternate triggers on the vulnerable 8.4.0 release.

Fix Coverage / Assumptions

The original advisory does not reference a vendor fix. Public disclosure (Jiva Security, 2026-07-06) confirms that Vtiger did not respond to the 90-day disclosure window and that no patch was released. A narrow fix that only inspected the module import path (Vtiger_PackageImport) would leave two structurally similar sinks exposed:

  • Vtiger_LanguageImport::import_Language() — no file content or extension validation.
  • Vtiger_LayoutImport::import_Layout() — partial PHP content validation that is bypassable.

The current code assumes that the import type alone (module, language, layout) is enough to determine which extraction logic to run, but it does not enforce a uniform safe-extraction policy across all three types.

Variant / Alternate Trigger

Two distinct, confirmed alternate triggers were found through the same authenticated admin endpoint.

Variant 1 — Language Pack Import
  • Entry point: index.php?module=ModuleManager&parent=Settings&view=ModuleImport&mode=importUserModuleStep1 (HTTP POST to importUserModuleStep2, then Basic&mode=importUserModuleStep3).
  • Dispatch: modules/Settings/ModuleManager/actions/Basic.php::importUserModuleStep3 creates new Vtiger_Language() when module_import_type == 'language'.
  • Extraction sink: vtlib/Vtiger/LanguageImport.php::import_Language().
  • Trigger: Upload a ZIP containing a valid manifest.xml with <type>language</type> and a <prefix> value, plus a PHP file under modules/shell.php. The sink rewrites the path to languages/<prefix>/shell.php.
  • Execution: Access http://<host>/languages/<prefix>/shell.php?cmd=<command>.
Variant 2 — Layout Import PHP-Filter Bypass
  • Entry point: Same Module Manager Import endpoint as above.

  • Dispatch: modules/Settings/ModuleManager/actions/Basic.php::importUserModuleStep3 creates new Vtiger_Layout() when module_import_type == 'layout'.

  • Extraction sink: vtlib/Vtiger/LayoutImport.php::import_Layout().

  • Trigger: Upload a ZIP containing a valid manifest.xml with <type>layout</type> and <parent>v7</parent>, plus a PHP file under layouts/<name>/skins/<name>/shell.php that uses the short-echo tag <?= ... ?>. The regex /(<\?php?(.*?))/i in import_Layout() does not detect <?=, so the file is extracted to layouts/<name>/skins/<name>/shell.php.

  • Execution: Access http://<host>/layouts/<name>/skins/<name>/shell.php?cmd=<command>.

  • Product/component: Vtiger CRM 8.4.0 (open-source PHP/MySQL CRM)

  • Affected versions: through 8.4.0 (tested on the 8.4.0 SourceForge release tarball)

  • Risk level: High

  • Consequences: Any authenticated administrator who can access the Module Manager Import feature can plant a persistent, unauthenticated web shell in languages/ or layouts/ in addition to modules/, achieving arbitrary remote code execution as the web-server user (www-data).

Impact Parity

  • Disclosed/claimed maximum impact: Authenticated remote code execution via a crafted module ZIP (code execution).
  • Reproduced impact from this variant run: The variant script logged into Vtiger 8.4.0 as admin, uploaded a language pack ZIP and a layout pack ZIP through the same Module Manager Import endpoint, and confirmed that both produced a working webshell returning the marker PRUVA_LANG_SHELL_OK and PRUVA_LAYOUT_SHELL_OK respectively, plus the output of the injected command (www-data).
  • Parity: full — the reproduced impact matches the claimed RCE impact.
  • Not demonstrated: A true bypass of a released vendor patch, because no patch is available.

Root Cause

The root cause is the same as the original vulnerability: Vtiger extracts attacker-supplied ZIP archives directly into web-accessible directories without a uniform, robust allowlist of safe file types and contents. The Module Manager Import dispatcher treats the three package types (module, language, layout) as separate code paths, but none of them:

  1. Stages the archive outside the web root before validation.
  2. Maintains a per-type allowlist of expected file extensions and relative paths.
  3. Rejects PHP files that are not legitimate, known source files for the package type.

The language import path has no validation at all. The layout import path has an incomplete regex that can be bypassed by the PHP short-echo tag. The module import path has no validation at all. The architectural trust boundary is identical: an authenticated admin can turn any of these imports into a persistent web shell.

Reproduction Steps

The full, automated reproduction is in bundle/vuln_variant/reproduction_steps.sh. At a high level it:

  1. Logs in to the already-running Vtiger 8.4.0 instance as the admin user.
  2. Builds a malicious language pack ZIP with <type>language</type>, a <prefix>, and modules/shell.php containing a PHP shell.
  3. Uploads the ZIP through the Module Manager Import endpoint and completes the import.
  4. Verifies the shell by accessing http://localhost/languages/<prefix>/shell.php?cmd=whoami.
  5. Builds a malicious layout pack ZIP with <type>layout</type>, <parent>v7</parent>, and layouts/<name>/skins/<name>/shell.php using the <?= short-echo tag.
  6. Uploads the ZIP through the same endpoint and completes the import.
  7. Verifies the shell by accessing http://localhost/layouts/<name>/skins/<name>/shell.php?cmd=whoami.
  8. Records the results to bundle/vuln_variant/proof.log and exits with code 1 because no vendor patch is available to test a true bypass.

Expected evidence of reproduction: Both webshells respond with their respective marker (PRUVA_LANG_SHELL_OK or PRUVA_LAYOUT_SHELL_OK) and the output of the injected command (e.g., www-data).

Evidence

  • bundle/logs/vuln_variant_reproduction_steps.log — full trace of the two variant tests.
  • bundle/vuln_variant/proof.log — structured result file (LANGUAGE_VARIANT=True, LAYOUT_VARIANT=True).
  • bundle/vuln_variant/reproduction_steps.sh — the idempotent reproduction script.
  • Key excerpts from bundle/logs/vuln_variant_reproduction_steps.log:
[+] Upload accepted: file=usermodule_1783466053.zip name=LangycQzbm type=language
[+] Install response: {"success":true,"result":{"success":true,"importModuleName":"LangycQzbm"}}
[*] Triggering language webshell: http://localhost/languages/langycqzbm/shell.php?cmd=whoami
[+] Webshell output: 200 PRUVA_LANG_SHELL_OK
www-data
www-data

[+] Upload accepted: file=usermodule_1783466053.zip name=LaynpRQix type=layout
[+] Install response: {"success":true,"result":{"success":true,"importModuleName":"LaynpRQix"}}
[*] Triggering layout webshell: http://localhost/layouts/LaynpRQix/skins/LaynpRQix/shell.php?cmd=whoami
[+] Webshell output: 200 PRUVA_LAYOUT_SHELL_OK
www-data
www-data

Environment captured during the run:

  • Vtiger CRM 8.4.0 (SourceForge tarball, md5 360f394f5f7ffabc89eaca05b18523f9)
  • Apache 2.4.66 + PHP 8.5 (mod_php)
  • MariaDB 11.8.6
  • Ubuntu 26.04 (resolute)

Recommendations / Next Steps

  • Immediate fix: Add a uniform, pre-extraction validation layer in the Module Manager import dispatcher (modules/Settings/ModuleManager/actions/Basic.php) before calling Vtiger_Package::import(), Vtiger_Language::import(), or Vtiger_Layout::import(). The validator should enforce a per-type allowlist of expected file extensions and relative paths, and reject any PHP file that is not a legitimate module/language/layout source file.
  • Fix layout content check: Replace the bypassable regex /(<\?php?(.*?))/i in vtlib/Vtiger/LayoutImport.php with a robust check (e.g., tokenization via token_get_all()) or, better, reject PHP files entirely in layout packs.
  • Fix MIME validation: Vtiger_Functions::verifyClaimedMIME() should compare file MIME types against a MIME type allowlist, not against the $upload_badext extension list.
  • Architectural fix: Stage all user-uploaded module/language/layout archives outside the document root. Copy only validated files into the application tree, and serve assets through an authenticated PHP handler that sets Content-Disposition: attachment for non-executable files.
  • Regression tests: Add tests that attempt to import each package type with an embedded PHP shell and assert rejection and that the PHP file is never created under modules/, languages/, or layouts/.

Additional Notes

  • Idempotency: The reproduction script was run twice consecutively against the same Vtiger 8.4.0 installation. Both runs succeeded, using unique module/language/layout names each time to avoid collisions.
  • Fixed version test: No vendor patch is available. The script therefore cannot demonstrate a true bypass of a fixed version and exits with code 1 even though the alternate triggers are confirmed on the vulnerable version.
  • No repro state mutation: The variant stage reused the existing 8.4.0 deployment created by the repro stage; it did not check out a different source ref or alter the original repro artifacts.
  • Third-party research alignment: The Jiva Security disclosure for CVE-2026-23698 explicitly flagged the language and layout import paths as structurally similar alternate routes, but did not publish a full PoC for them. This run provides that validation.

CVE-2026-23698 Reproduction Transcript

The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired.

Full session Replay every step — scrub the timeline or play it back.

Event 1/40
0:001:30
0:00
session startedaccounts/fireworks/models/kimi-k2p7-code · GHSA-JF2J-JHVF-RC56 · REPRO-20
0:05
0:07
web search
0:08
0:13
0:14
0:16
0:17
0:29
0:30
web search
0:35
0:36
web search
0:55
0:56
extract_facts
no facts extracted
0:56
0:56
0:56
supportrepro
1:22
1:24
1:24
1:24
1:25
1:25
1:26
1:27
1:27
1:27
1:30
08 · How to Fix

How to Fix CVE-2026-23698

Coming soon

Step-by-step mitigation and hardening guidance for CVE-2026-23698 — configuration checks, workarounds where no patch exists, and how to verify you're protected — is on the way.

10 · FAQ

FAQ: CVE-2026-23698

How does the CVE-2026-23698 exploit work?

An authenticated admin uploads a ZIP through the Module Manager import endpoint containing a manifest.xml plus a malicious PHP file (e.g. shell.php). Once extracted, the PHP file sits inside modules/<moduleName>/ where it is directly reachable via HTTP, bypassing Vtiger's routing/authentication layer and executing as the web-server user.

Which versions of Vtiger CRM are affected by CVE-2026-23698?

Vtiger CRM through 8.4.0 is affected, via the Module Manager import code path present across the 8.x line.

How severe is CVE-2026-23698?

High severity, CVSS 8.6. It requires an authenticated admin account with access to the Module Manager, but leads to persistent, unauthenticated remote code execution as the web-server user once the malicious PHP file is planted.

How can I reproduce CVE-2026-23698?

Download the verified script from this page and run it in an isolated environment against Vtiger CRM 8.4.0. It logs in as an administrator, uploads a malicious module ZIP through the Module Manager import endpoint, and confirms the planted PHP file executes when requested directly over HTTP.
11 · References

References for CVE-2026-23698

Authoritative sources for CVE-2026-23698 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.