PR-5.4-dev Pending

User tests: Successful: Unsuccessful:

avatar pwner-jw
pwner-jw
8 Jul 2026

extract.php read ZIP entry filenames directly from the archive's local file headers and used them unvalidated in mkdir() and fopen() calls during extraction. A crafted entry name containing ".." segments or an absolute path (e.g. "../../../../etc/cron.d/x" or "/var/www/other-site/shell.php") could therefore write files outside the intended destination directory, commonly known as a Zip Slip vulnerability.

This adds isPathTraversalAttempt(), which rejects entry names that are absolute (Unix root, Windows drive letter, or UNC path) or contain a ".." path segment. The check runs on the raw entry name before addPath is prepended, and reuses the existing $isBannedFile / skip-and-seek mechanism already used for "." and ".." basenames and the skipFiles list, so rejected entries are safely skipped without disrupting the ZIP read pointer.

No behavior change for well-formed archives.

Pull Request resolves # .

  • I read the Generative AI policy and my contribution is either not created with the help of AI or is compatible with the policy and GNU/GPL 2 or later.

Summary of Changes

Added a new private method isPathTraversalAttempt() to ZIPExtraction in administrator/components/com_joomlaupdate/extract.php, and one additional check in readFileHeader() that marks entries as banned (using the existing $isBannedFile skip logic) when the raw entry filename is an absolute path or contains a .. path segment.

Testing Instructions

  1. Apply this patch to a Joomla installation.
  2. Craft a test ZIP archive containing an entry with a path-traversal name, e.g. ../../../evil.php, an absolute path /tmp/evil.php, or a Windows-style C:\evil.php.
  3. Also include a normal, well-formed entry, e.g. administrator/components/com_example/example.php, in the same archive.
  4. Trigger extract.php against this archive (e.g. via the update flow, or by calling it directly with the required password/task parameters).
  5. Confirm the malicious entries are skipped (no file is written outside the destination directory) and the well-formed entry extracts normally to the expected path.

Actual result BEFORE applying this Pull Request

A ZIP entry with a ..-containing or absolute path name is extracted using its literal, unvalidated path, allowing mkdir()/fopen() calls to create directories and write files outside the intended extraction root.

Expected result AFTER applying this Pull Request

Entries with .. segments or absolute paths are detected before extraction and skipped, consistent with how other banned entries (e.g. ./.. basenames, skipFiles list) are already handled. Well-formed archives extract unchanged.

Link to documentations

Please select:

  • Documentation link for guide.joomla.org:
  • No documentation changes for guide.joomla.org needed
  • Pull Request link for manual.joomla.org:
  • No documentation changes for manual.joomla.org needed
avatar pwner-jw pwner-jw - open - 8 Jul 2026
avatar pwner-jw pwner-jw - change - 8 Jul 2026
Status New Pending
avatar joomla-cms-bot joomla-cms-bot - change - 8 Jul 2026
Category Administration com_joomlaupdate
avatar pwner-jw
pwner-jw - comment - 8 Jul 2026

Hi @brianteeman, thanks for flagging — this was already reported through the
official channel and reviewed by the Security Strike Team. Harald assessed it as not meeting the security-issue bar, since exploitation requires Super User access, which already implies full code execution via the standard extension/update upload flow. He suggested I open this as a normal hardening PR on the public tracker, which is what this is.

avatar brianteeman
brianteeman - comment - 8 Jul 2026

Strange, because yes it is correct that you would need to be a Super User and a super user can knowingly do all sorts of things in this case you are describing the potential of a super user being tricked into unkowingly uploading a zipslipped joomla update

avatar richard67 richard67 - change - 8 Jul 2026
Title
[com_joomlaupdate] Fix path traversal (Zip Slip) in extract.php
[5.4] [com_joomlaupdate] Fix path traversal (Zip Slip) in extract.php
avatar richard67 richard67 - edited - 8 Jul 2026
avatar pwner-jw
pwner-jw - comment - 8 Jul 2026

@brianteeman Thanks for reviewing this.

If this gets merged, I'd appreciate it if the Security Strike Team could revisit whether it qualifies for a CVE. If not, I'd be grateful for an acknowledgment of the security hardening contribution.

avatar pwner-jw pwner-jw - change - 12 Jul 2026
Labels Added: PR-5.4-dev
avatar pwner-jw
pwner-jw - comment - 14 Jul 2026

@brianteeman @richard67 any update?

avatar alikon
alikon - comment - 14 Jul 2026

@pwner-jw
for speed-up the tests can you provide "a test ZIP archive containing an entry with a path-traversal name...."

avatar pwner-jw
pwner-jw - comment - 17 Jul 2026

@alikon were u able to test?

avatar brianteeman
brianteeman - comment - 17 Jul 2026

I can confirm that before applying the pr then performing an update with the supplied zipslip wrote a php file to the root of the web space
I can confirm that after applying pr then the php file was not written

As I stated before you would need to be a super user but I can see a scenario where a super user was tricked into downloading and then uploading a malicious joomla update zip

Not marking it as a success or failure as Idont know enough about this to know if the PR is sufficient

avatar pwner-jw
pwner-jw - comment - 18 Jul 2026

@brianteeman Agreed, and that's the distinction worth flagging back to the JSST. "Requires Super User" conflates the privilege needed to trigger extraction with the intent needed to cause the traversal. A Super User running the normal update flow isn't consenting to writes outside administrator/ they're consenting to a scoped install. If the ZIP source is attacker-influenced (compromised update stream, malicious package, social-engineered install), their legitimate action becomes the delivery mechanism for an out-of-scope write, e.g. a web shell in a sibling site or a cron job. That's privilege escalation from "site admin" to "host compromise," not a no-op.
Either way, functionally this is the same bug class as every other Zip Slip CVE assigned in extraction libraries, none of those needed a malicious caller, only a malicious archive.

avatar pwner-jw
pwner-jw - comment - 18 Jul 2026

thanks, done

avatar kdalal-vulncheck
kdalal-vulncheck - comment - 20 Jul 2026

Hello @richard67 Richard,
This issue is fixed in 9678a17 can you please merge this pull request?

avatar richard67
richard67 - comment - 20 Jul 2026

Hello @richard67 Richard, This issue is fixed in 9678a17 can you please merge this pull request?

@kdalal-vulncheck Each pull request needs 2 successful human test before it can be considered to be merged.

avatar pwner-jw
pwner-jw - comment - 26 Jul 2026

Hello @richard67 , could you please share an update on when the manual checks are expected to be completed? This issue is critical, so a timeline would be really helpful.

avatar richard67
richard67 - comment - 26 Jul 2026

Hello @richard67 , could you please share an update on when the manual checks are expected to be completed? This issue is critical, so a timeline would be really helpful.

@pwner-jw Joomla is a project of a community of volunteers. So we all do it in our spare time. Everybody who can contribute here e.g. by opening issues or creating pull requests can also test other people's pull request. I have no influence on that.

This issue is critical

Where is it critical? As updating the core is restricted to superusers only, where is it critical in practice?

Besides that: Keeping maintainers or release managers busy with pinging them just because of impatience does not really help the project.

avatar pwner-jw
pwner-jw - comment - 27 Jul 2026

Thanks for the feedback, Richard. You're right, I realise I've followed up a few times, and I can see how that creates unnecessary noise. That wasn't my intention, and I appreciate that everyone working on Joomla is volunteering their time.

I'll hold off on further follow-ups and wait for the review process. Thanks again to everyone involved in maintaining the project.

avatar pwner-jw
pwner-jw - comment - 27 Jul 2026

You're right, I realise I've followed up a few times, and I can see how that creates unnecessary noise. That wasn't my intention, and I appreciate that everyone working on Joomla is volunteering their time.

I'll hold off on further follow-ups and wait for the review process. Thanks again to everyone involved in maintaining the project.

avatar kdalal-vulncheck
kdalal-vulncheck - comment - 11 Aug 2026

Hello @richard67 Richard,
Has this issue gone through 2 successful human test? If so, can you please merge this pull request. This issue is fixed in 9678a17.

avatar richard67
richard67 - comment - 11 Aug 2026

Hello @richard67 Richard, Has this issue gone through 2 successful human test? If so, can you please merge this pull request. This issue is fixed in 9678a17.

@kdalal-vulncheck WHy do you put pressure on me? We will merge it when we have time. Besides that you will see on GitHub in the CI checks at the bottom if the PR has successful tests or not. Currently it still needs 2 tests. When it has them, the RTC label will be set by a maintainer or release manager.

Please stop to keep maintainers and release managers like me unnecessarily busy by pinging them for no reason. The issue which this PR fixes is nothing urgent.

avatar SniperSister
SniperSister - comment - 17 Aug 2026

@kdalal-vulncheck please go check the discloure@ mailbox of your company.

Your company has yet again violated the CVE CNA coverage of Joomla for all Joomla related issues and assigned a CVE ID to an behavior that has clearly been assessed as "not as security issue" by the vendor. The violation of our CNA scope has now happend multiple times and I'm really starting to question your internal processes.

avatar SniperSister
SniperSister - comment - 17 Aug 2026

@kdalal-vulncheck please go check the disclosure@ mailbox of your company.

Your company has yet again violated the CVE CNA coverage of Joomla for all Joomla related issues and assigned a CVE ID to an behavior that has clearly been assessed as "not as security issue" by the vendor. The violation of our CNA scope has now happend multiple times and I'm really starting to question your internal processes.

avatar kdalal-vulncheck
kdalal-vulncheck - comment - 17 Aug 2026

Hello @SniperSister David,

Apologies — CVE-2026-73327 was assigned in error. We don't assign for products in another CNA's scope, and Joomla core is clearly yours. That was by mistake.

We're rejecting the record now with scope as the stated reason.

avatar muhme
muhme - comment - 18 Aug 2026

@pwner-jw There are review changes from @QuyTon open, could you please resolve them?

avatar pwner-jw
pwner-jw - comment - 18 Aug 2026

@muhme and @QuyTon Sorry for the late reply.

I’ve kept this as a separate if intentionally. The existing checks and isPathTraversalAttempt() represent independent reasons for marking an archive entry as banned: the former handles the legacy ./.. filename check, while the new check covers absolute paths (Unix, Windows drive/UNC) and .. path segments anywhere in the raw ZIP entry name. The $skipFiles check below is also an independent configured exclusion.

All three checks only contribute to the $isBannedFile flag; the entry is skipped once that flag is true. Using elseif here would only short-circuit evaluation of the subsequent validation rules and doesn't provide any additional security benefit. I therefore prefer keeping the checks independent while preserving the existing banned-file handling semantics.

avatar pwner-jw pwner-jw - change - 18 Aug 2026
Labels Added: Updates Requested
avatar QuyTon QuyTon - change - 30 Aug 2026
Labels Removed: Updates Requested

Add a Comment

Login with GitHub to post a comment