Skip to main content
CVE-2026-48907 Critical Patch Available

CVE-2026-48907: Joomla Content Editor — Unauthenticated RCE via File Upload

CVE Details

CVE ID CVE-2026-48907
CVSS Score 10
Severity Critical
Vendor Widget Factory
Product Joomla Content Editor (JCE)
Patch Status Available
Published June 17, 2026
EPSS Score 80.4%
CISA Patch Deadline ⚠ July 8, 2026 Federal deadline passed

Background

CVE-2026-48907 is a critical unauthenticated remote code execution vulnerability in the Joomla Content Editor (JCE) plugin, developed by The Widget Factory and Ryan Demmer. JCE is one of the most widely installed Joomla extensions, with installations across a significant proportion of the approximately 2 million active Joomla sites globally.

The vulnerability exists in the plugin’s profile import endpoint. A combination of missing authentication checks, absent file extension validation, and explicitly disabled upload safety controls allows any unauthenticated attacker to upload a PHP webshell and execute it within seconds. The exploit requires only a valid CSRF token, which is trivially obtainable from any public-facing Joomla page.

CISA added CVE-2026-48907 to the Known Exploited Vulnerabilities (KEV) catalog on June 16, 2026, with a remediation deadline of June 19, 2026. The vulnerability is actively exploited by automated botnets performing opportunistic scanning. A public proof-of-concept and Docker-based exploitation environment are available on GitHub.

CVSS 4.0 score: 10.0 (CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H/E:A/AU:Y).

Technical Mechanism

The vulnerability is a three-part exploit chain, each weakness individually necessary for full exploitation.

Weakness 1: Missing Authorization on the Profile Import Endpoint

The endpoint index.php?option=com_jce&task=profiles.import performed CSRF token validation only — it did not check whether the requesting user was authenticated or held the core.manage privilege. CSRF tokens in Joomla are embedded in public-facing page HTML and JavaScript metadata. Any unauthenticated client that makes a GET request to the Joomla homepage can harvest a valid CSRF token and replay it in a subsequent POST to the import endpoint. The CSRF check was purely an origin control, not an access control.

Weakness 2: No File Extension Validation

The upload handler called File::makeSafe() to sanitize the uploaded filename. This function sanitizes special characters but does not inspect or restrict file extensions. A file named nuclei-deadbeef.xml.php passes makeSafe() unchanged. The double-extension filename causes the web server to interpret the file as PHP when requested.

Weakness 3: Upload Safety Controls Explicitly Disabled

The upload call used the following invocation:

File::upload($source, $destination, false, true)

The fourth argument ($allow_unsafe) was set to true. This parameter explicitly disables Joomla’s built-in extension blacklist, which would normally reject .php and other executable extension types. The platform’s own defense-in-depth was disabled at the code level.

Combined Attack Surface

The intersection of these three weaknesses produces a complete pre-authentication PHP upload and execution primitive with no technical barriers.

Real-World Exploitation Evidence

Exploit Chain (step by step):

  1. Token extraction: Attacker sends GET / and extracts the CSRF token from the HTML response.
  2. Webshell upload: Attacker sends POST /index.php?option=com_jce&task=profiles.import as a multipart/form-data request with a PHP webshell embedded in a file named nuclei-<hash>.xml.php. The file lands in the Joomla /tmp/ directory by default.
  3. RCE trigger: Attacker sends GET /tmp/nuclei-<hash>.xml.php. Because Joomla’s default configuration permits PHP execution from /tmp/, the shell executes immediately.

Full webshell variants also upload to /images/, /media/, or /images/jce/ depending on installation configuration.

The minimal confirmation payload is <?= 45*69 ?>, which returns 3105 on a vulnerable target. The public PoC (github.com/ywh-jfellus/CVE-2026-48907) includes a Docker Compose environment for side-by-side testing of vulnerable (2.9.99.4) and patched (2.9.99.5) versions.

Threat Actor Context:

No specific named threat actor or ransomware group has been attributed to exploitation at this time. Observed exploitation is opportunistic and automated: botnet scanning began within days of public PoC publication. Observed post-exploitation activity includes defacement and cryptocurrency mining implant deployment. The attack is rated automatable (AU:Y) in the CVSS 4.0 vector; at scale, mass exploitation of unpatched Joomla installations is straightforward. The CISA KEV listing with a three-day remediation deadline reflects both the severity and the breadth of active scanning.

Impact Assessment

Successful exploitation gives the attacker arbitrary PHP code execution on the web server with the permissions of the web application process. From that position, an attacker can exfiltrate website databases, deface or replace content, install persistent webshells for ongoing access, and pivot to other services on the hosting server.

Joomla powers approximately 2 million websites globally, and JCE is among the most widely installed extensions. The unauthenticated access requirement means no social engineering or credential compromise is needed — any internet-connected scanner can identify and exploit vulnerable instances automatically. The public PoC, Docker-based exploitation environment, and CISA-mandated three-day remediation deadline reflect both the severity and the pace of mass opportunistic exploitation campaigns already underway at time of publication.

Affected Versions

ProductAffected VersionsFixed Version
Joomla Content Editor (JCE)1.0.0 through 2.9.99.42.9.99.5 (initial fix); 2.9.99.6 (hardened, preferred)
JCE for Joomla 3.xAll versionsNo patch available — platform incompatibility

JCE 2.9.99.5 introduces the initial patch (released June 3, 2026, two days before CVE assignment). JCE 2.9.99.6 adds further hardening and codebase-wide security review (released June 8, 2026). The vendor has also released free patch packages for older 2.7.x, 2.8.x, and 2.9.x branches to address sites running non-current major versions.

Joomla 3.x installations cannot receive the current patch due to platform incompatibility and remain exposed. Legacy Joomla 3.x sites running JCE should be treated as compromised-pending-discovery.

Remediation Steps

Immediate action: Update JCE to version 2.9.99.6 or later via the Joomla Extension Manager. Version 2.9.99.5 resolves the core vulnerability; 2.9.99.6 adds additional hardening and is preferred.

For sites unable to update immediately: The vendor has released free patch packages for older 2.7.x, 2.8.x, and 2.9.x branches. Apply the appropriate legacy patch if a version upgrade is not immediately feasible.

For Joomla 3.x sites: No patch is available. Consider these installations unmitigatable and escalate to full assessment and migration planning.

Patches applied in 2.9.99.5+:

  1. Added $user->authorise('core.manage', 'com_jce') authentication check on the import endpoint — unauthenticated requests are now rejected before any file handling occurs.
  2. Extension allowlist: only .xml extensions are accepted, validated via pathinfo($filename, PATHINFO_EXTENSION).
  3. Removed the $allow_unsafe=true parameter — Joomla’s built-in extension blacklist is now active for all uploads.
  4. Upload size cap: 512 KB maximum.
  5. XXE protection: external entity loading disabled in the XML parser handling profile imports.
  6. XML field allowlist: only known-safe fields are processed from imported profile documents.

Network-level workaround (temporary, not a substitute for patching):

Block or rate-limit POST requests to paths matching index.php where the query string contains option=com_jce and task=profiles.import at the WAF or reverse proxy layer. This does not remediate the underlying vulnerability but reduces automated exploitation exposure while patching is underway.

Detection Guidance

Web server access logs:

Look for POST requests to /index.php where the query string contains com_jce and task=profiles.import. Any such POST from a session not authenticated as a Joomla admin is suspicious. Volume and IP diversity will indicate automated scanning.

grep "com_jce.*task=profiles.import" /var/log/apache2/access.log | grep "POST"

Filesystem indicators:

Scan for PHP files in locations where no PHP should exist:

  • /tmp/*.php or /tmp/*.xml.php — primary drop location
  • /images/jce/*.php
  • /media/*.php
  • Any file matching nuclei-*.xml.php under the Joomla webroot
find /var/www/html -name "*.php" -newer /var/www/html/configuration.php -not -path "*/libraries/*" -not -path "*/administrator/*"

JCE admin panel:

Rogue profiles created by the exploit appear at the top of the JCE profile list with auto-generated names. A secondary side-effect of exploitation is the removal of toolbar buttons from editor configurations. Sudden disappearance of editor toolbars from the Joomla backend is an indirect indicator.

IOCs:

  • Filename pattern: nuclei-[a-f0-9]+\.xml\.php
  • POST request URI: /?option=com_jce&task=profiles.import or /index.php?option=com_jce&task=profiles.import
  • User-agent pattern: commonly automated (scripted) clients with minimal or absent user-agent strings in exploitation tooling

YARA-compatible file detection:

rule CVE_2026_48907_JCE_Webshell {
    strings:
        $php_tag = "<?php"
        $system = "system(" nocase
        $eval = "eval(" nocase
        $passthru = "passthru(" nocase
    condition:
        $php_tag and (1 of ($system, $eval, $passthru))
        and filename matches /nuclei-[a-f0-9]+\.xml\.php/
}

Timeline

DateEvent
2026-06-03JCE 2.9.99.5 patch released
2026-06-05CVE-2026-48907 assigned by Joomla! Project CNA
2026-06-08JCE 2.9.99.6 hardening release
2026-06-09Public PoC documented (GitHub, Sploitus)
2026-06-12Active exploitation confirmed by vendor and external researchers
2026-06-16Added to CISA KEV catalog

References