# Patch Analysis for CVE-2026-48939 Variant Search

## Target and available fix artifacts

- Product: iCagenda Joomla extension (`com_icagenda`).
- Submitted vulnerable target: official iCagenda 4.0.7 package, tested by the repro stage on Joomla `joomla:6.0-php8.3-apache`.
- Fixed target available in this workspace: official iCagenda 4.0.8 package, also tested by the repro stage.
- No upstream git repository or fix commit hash was provided in the ticket. The exact tested source identity is therefore the official package version plus package hash, not a git commit.

## Target security policy / threat-model scope

The extracted iCagenda packages in this workspace do not contain a `SECURITY.md`, threat-model document, or serialization/security-scope document. A web search found the Joomla CMS security policy, which directs Joomla extension vulnerabilities to the Joomla Vulnerable Extensions List, and the iCagenda 4.0.8 security-release changelog. No iCagenda-specific policy was found that excludes unauthenticated public file upload or web-accessible PHP execution from security scope.

For this analysis, the relevant trust boundary is the public Joomla frontend event submission form. When `submitAccess` allows public submissions and `submit_fileDisplay` enables the attachment field, an unauthenticated remote user controls multipart upload fields delivered to iCagenda server-side code. Saving attacker-controlled files under the executable web root is in scope.

## What changed in the 4.0.8 fix

The 4.0.7 to 4.0.8 package diff shows two relevant server-side changes.

### Frontend public submit model

File: `components/com_icagenda/src/Model/SubmitModel.php` in an installed Joomla site (source package path: `site/src/Model/SubmitModel.php`).

1. 4.0.8 imports Joomla's media validation helper:

```php
use Joomla\CMS\Helper\MediaHelper;
```

2. In `SubmitModel::submit()`, immediately after reading frontend files from `$jinput->files->get('jform')`, 4.0.8 performs an early validation check on `$files['file']`:

```php
$fileLink = '';

if ($file && !empty($file['name'])) {
    $helper = new MediaHelper();
    $can = $helper->canUpload($file);

    if (!$can) {
        return false;
    }

    $fileLink = $this->frontendFileUpload($file);
}
```

3. 4.0.8 also adds the same `MediaHelper::canUpload($file)` check at the beginning of `frontendFileUpload($file)` before preserving the original extension and calling `File::upload($src, $dest, false)` into `images/icagenda/frontend/attachments/`.

### Administrator event model

File: `administrator/components/com_icagenda/src/Model/EventModel.php` in an installed Joomla site (source package path: `admin/src/Model/EventModel.php`).

The 4.0.8 package also imports `MediaHelper` and validates administrator-side event attachment uploads before calling `upload($files['file'])`, which writes to `images/icagenda/files/`:

```php
if ($files && !empty($files['file']['name'])) {
    $helper = new MediaHelper();
    $can = $helper->canUpload($files['file']);

    if (!$can) {
        $this->setError(Text::_('JLIB_MEDIA_ERROR_UPLOAD_INPUT'));
        return false;
    }

    $fileUrl = $this->upload($files['file']);
}
```

This administrator path is not unauthenticated, but it shows the package maintainer attempted to cover the same dangerous upload primitive in another event attachment entry point.

## Behavior before and after the fix

### 4.0.7 vulnerable behavior

- `SubmitModel::submit()` reads `$files['file']` from the public form.
- It assigns `$eventData->file = ! empty($file['name']) ? $this->frontendFileUpload($file) : ''` with no server-side file-type allow-list.
- `frontendFileUpload()` keeps the original extension, slugifies only the basename, creates `images/icagenda/frontend/attachments/`, and calls `Joomla\Filesystem\File::upload($src, $dest, false)`.
- On the Joomla Apache PHP image used in repro, Apache's PHP handler applies to files ending in `.php`; the uploaded attachment is web-accessible and executes when requested.

### 4.0.8 fixed behavior

- The same public event form path calls `MediaHelper::canUpload()` before storage.
- Joomla `MediaHelper::canUpload()` rejects filenames with executable extensions anywhere in the dotted filename parts. It merges `MediaHelper::EXECUTABLES` with `InputFilter::FORBIDDEN_FILE_EXTENSIONS`, including `php`, `phps`, `pht`, `phtml`, `php3`, `php4`, `php5`, `php6`, `php7`, `php8`, `phar`, `inc`, `pl`, `cgi`, `fcgi`, `java`, `jar`, `py`, and `aspx`.
- It also enforces Joomla media upload extension and MIME restrictions for the default media component parameters.
- The repro-stage fixed negative control showed iCagenda 4.0.8 did not create the attachment directory for a `.php` payload and a request to the would-be shell returned 404.

## Assumptions made by the fix

1. Every file attachment write reaches either `SubmitModel::frontendFileUpload()` or `EventModel::upload()`.
2. Joomla `MediaHelper::canUpload()` accurately represents the extension/MIME policy for iCagenda attachments.
3. Rejecting executable extensions before `File::upload()` is sufficient when the destination is still under a web-accessible directory.
4. The server executes only extensions listed in Joomla's executable/forbidden extension lists. In the tested Apache image, only `.php` is handled by the generic Docker PHP handler, and `InputFilter::FORBIDDEN_FILE_EXTENSIONS` also blocks common PHP aliases such as `.phtml`, `.pht`, `.php8`, and `.phar`.
5. The unauthenticated attack surface is the public submit endpoint gated by a menu item and `submitAccess`/`submit_fileDisplay` component configuration.

## Code paths and inputs not covered or considered during variant search

- `frontendImageUpload($image)` still does not call `MediaHelper::canUpload()`. It implements its own image-extension logic and writes to `images/icagenda/frontend/images/`. However, this is a different field (`jform[image]`), a different storage directory, and the filename extension is ultimately image-oriented. A polyglot `GIF89a...<?php ... ?>` named `.gif` can be stored, but it is served as an image/static file, not executed by the tested Apache PHP handler. A `.php` image filename causes `getimagesize()`-based extension correction and does not preserve a `.php` destination in this path.
- The public submit controller validates CSRF, public access, and the active menu item; changing only URL parameters does not create a separate upload sink.
- The administrator `EventModel::upload()` path is now covered by `MediaHelper::canUpload()` in 4.0.8 and requires authenticated administrator access, so it does not cross the same unauthenticated trust boundary.
- The package search found no other public frontend controller/model paths that call `File::upload()` for `jform[file]` attachments.

## Variant search conclusion

The most meaningful sibling candidate was the public `jform[image]` upload field because it is unauthenticated when the event submit form is public and still writes into the Joomla web root. Runtime testing should compare iCagenda 4.0.7 and 4.0.8 with the same image-field payload. Based on source inspection, this candidate is expected to be stored only as `.gif`/image content and not executed as PHP in either version; therefore it is not a bypass of the attachment fix unless a server is configured to execute image extensions as PHP, which is outside the tested default Joomla Apache deployment.

No confirmed bypass was identified by source inspection. The fix appears to cover the originally vulnerable public attachment field and the related administrator attachment path. Remaining hardening recommendation: store all user-uploaded files outside executable web roots or ship web-server deny rules for `images/icagenda/frontend/attachments/` and `images/icagenda/frontend/images/`, so future extension allow-list mistakes cannot become RCE.