CVE-2026-45008: phpMyFAQ: Path Traversal in Client::deleteClientFolder enables arbitrary directory deletion by non-super-admin admins

Published May 6, 2026
·
Updated

Summary

Client::deleteClientFolder() in phpmyfaq/src/phpMyFAQ/Instance/Client.php:583 takes a URL from the caller, strips the https:// prefix, and passes the remainder to Filesystem::deleteDirectory() relative to the multisite clientFolder. No path-traversal validation runs. An admin with the INSTANCEDELETE permission (a role short of SUPERADMIN) submits https://../../../<path> as the client URL and the server recursively deletes arbitrary directories under the web user's rights. Same pattern and reachability as GHSA-38m8-xrfj-v38x, which the project accepted at High severity three weeks earlier.

Details

phpmyfaq/src/phpMyFAQ/Instance/Client.php:583-591:

php public function deleteClientFolder(string $sourceUrl): bool { if (!$this->isMultiSiteWriteable()) { return false; }

$sourcePath = strreplace(search: 'https://', replace: '', subject: $sourceUrl); return $this->filesystem->deleteDirectory($this->clientFolder . $sourcePath); }

strreplace strips the scheme but does nothing about ../ segments. The concatenation $this->clientFolder . $sourcePath directly feeds the filesystem call, which traverses above clientFolder without complaint.

Callers feed the URL from the HTTP request body:

phpmyfaq/src/phpMyFAQ/Controller/Administration/Api/InstanceController.php:184:

php if (1 !== $instanceId && $client->deleteClientFolder($clientData->url) && $client->delete($instanceId)) {

$clientData->url comes from jsondecode($request->getContent()). The route is admin.api.instance.delete, gated by INSTANCEDELETE. The controller does not validate the URL against a scheme list or canonicalize the path before handing it to deleteClientFolder().

InstanceController.php:144 (edit path) and Controller/Administration/InstanceController.php:151 (form path) both reach the same sink through different entry points.

Precedent

GHSA-38m8-xrfj-v38x (2026-03-31) disclosed the identical bug class in MediaBrowserController::index(): an admin-gated API endpoint concatenates a user-supplied filename to a base directory without traversal validation. phpMyFAQ accepted that report at High severity. The present finding is the same root cause in a different controller; the project's INSTANCEADD / INSTANCEDELETE permission is a granular admin right, not SUPERADMIN, so a lower-tier admin can reach the sink.

Proof of Concept

Prerequisites: a phpMyFAQ 4.2.x instance with the multisite subsystem bootstrapped (there must be a non-primary instance present for the delete controller branch to fire). Alice is an admin with INSTANCEADD and INSTANCEDELETE rights, no SUPERADMIN flag.

Step 1: Alice authenticates and retrieves the CSRF token for the instance admin page.

Step 2: Alice creates an instance whose url encodes a traversal payload. The create path at InstanceController.php:144 already concatenates to the clientFolder through the same deleteClientFolder('https://' . $hostname) call:

bash curl -sS -b "$ALICECOOKIE" -X POST "$BASE/admin/api/instance" \ -H "Content-Type: application/json" -H "x-csrf-token: $CSRF" \ -d '{"url":"https://../../../tmp/pmf-poc/","instance":"poc","comment":"poc","email":"a@b","admin":"alice","password":"poc1234!"}'

Step 3: Alice deletes the instance. The request body names the instance id to delete; the controller hands clientData->url directly to deleteClientFolder:

bash curl -sS -b "$ALICECOOKIE" -X POST "$BASE/admin/api/instance/2" \ -H "Content-Type: application/json" -H "x-csrf-token: $CSRF" \ -d '{"url":"https://../../../tmp/pmf-poc/"}'

The server computes $sourcePath = '../../../tmp/pmf-poc/', concatenates to <clientFolder>/, and recursively deletes the resulting path.

Live verification was not attempted against the test instance because the INSTANCEDELETE path requires the multisite/ subsystem to be bootstrapped with at least one non-primary instance; see InstanceController.php:184. The code path is unambiguous and the precedent GHSA confirmed the same admin gating was considered in-scope.

Impact

Any phpMyFAQ admin holding INSTANCEADD + INSTANCEDELETE but not SUPERADMIN can delete arbitrary directories writable by the PHP process. Outcomes:

- Destroy other tenants' data on a shared multisite deployment by traversing above the clientFolder into peer directories. - Delete phpMyFAQ's own content/, config/, or cache directories and lock the install out. - On a hosted deployment, overwrite or delete files anywhere under the web user's reach, including customer uploads outside phpMyFAQ.

phpMyFAQ's permission model gives INSTANCEADD / INSTANCEDELETE as a role that a hosting operator may delegate to a subordinate admin without granting SUPERADMIN. That delegation is now a direct path-traversal-delete primitive.

Recommended Fix

Canonicalize and validate the URL before forming the filesystem path.

phpmyfaq/src/phpMyFAQ/Instance/Client.php:583:

php public function deleteClientFolder(string $sourceUrl): bool { if (!$this->isMultiSiteWriteable()) { return false; }

$parsed = parseurl($sourceUrl); if (!isarray($parsed) || !isset($parsed['host']) || ($parsed['scheme'] ?? '') !== 'https') { return false; }

$host = $parsed['host']; if (!pregmatch('/^[a-z0-9][a-z0-9.-]$/i', $host)) { return false; }

$target = realpath($this->clientFolder . $host); $root = realpath($this->clientFolder); if ($target === false || $root === false || !strstartswith($target, $root . DIRECTORYSEPARATOR)) { return false; }

return $this->filesystem->deleteDirectory($target); }

parseurl rejects malformed inputs, the regex pins the host to valid DNS characters (no /, no ..), and the realpath check ensures the resolved target lives under clientFolder. Apply the same canonicalization at the controller layer (InstanceController::add, ::update, ::delete) so the URL is validated before every call that touches the filesystem.

--- Found by aisafe.io

Other sources

phpMyFAQ before 4.1.2 contains a path traversal vulnerability in Client::deleteClientFolder that allows admins with INSTANCEDELETE permission to delete arbitrary directories. Attackers can submit traversal sequences like https://../../../<path> in the client URL parameter to recursively delete directories outside the intended clientFolder scope.

— MITRE

phpMyFAQ: Path Traversal in Client::deleteClientFolder enables arbitrary directory deletion by non-super-admin admins

— Packagist

Affected Software

5 affected componentsFixes available
PhpMyFaq phpmyfaq<4.1.2
composer/phpmyfaq/phpmyfaq<=4.1.1
composer/thorsten/phpmyfaq<=4.1.1
composer/phpmyfaq/phpmyfaq<=4.1.1
4.1.2
composer/thorsten/phpmyfaq<=4.1.1
4.1.2

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade composer/phpmyfaq/phpmyfaq to a version that resolves this vulnerability.

    Fixed in 4.1.2
  2. Upgrade

    Upgrade composer/thorsten/phpmyfaq to a version that resolves this vulnerability.

    Fixed in 4.1.2
  3. Upgrade

    Upgrade phpMyFAQ to a version that resolves this vulnerability.

    Fixed in 4.1.2
  4. Compensating control

    Canonicalize and validate the client URL before forming filesystem paths or calling deleteClientFolder(). Apply this at InstanceController::add, ::update, and ::delete: parse the URL, require a valid host matching /^[a-z0-9][a-z0-9.-]*$/i, reject malformed or unsupported schemes, resolve the target with realpath, and require the resolved target to remain under clientFolder.

Event History

May 6, 2026
Advisory Published
via GitHub·08:47 PM
Data Sourced
via GitHub·08:47 PM
DescriptionSeverityWeaknessAffected Software
Data Sourced
via Packagist·08:47 PM
DescriptionSeverityAffected Software
May 15, 2026
CVE Published
via MITRE·06:36 PM
Data Sourced
via MITRE·06:36 PM
DescriptionSeverityWeakness
Data Sourced
via NVD·07:17 PM
DescriptionSeverityWeakness

Frequently Asked Questions

1

What is the severity of CVE-2026-45008?

CVE-2026-45008 is classified as a critical vulnerability due to its potential to allow unauthorized directory deletion.

2

How do I fix CVE-2026-45008?

To resolve CVE-2026-45008, upgrade to phpMyFAQ version 4.1.2 or later.

3

Who is affected by CVE-2026-45008?

CVE-2026-45008 affects phpMyFAQ versions prior to 4.1.2 that allow admins with INSTANCE_DELETE permission to exploit the vulnerability.

4

What kind of attack is possible with CVE-2026-45008?

CVE-2026-45008 allows attackers to execute path traversal attacks to delete arbitrary directories.

5

What components of phpMyFAQ are vulnerable in CVE-2026-45008?

The vulnerability exists specifically in the Client::deleteClientFolder function of phpMyFAQ.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203