GHSA-43c9-gw4x-pcx6
HIGHAuthenticated arbitrary file deletion in YesWiki
EPSS Exploitation Probability
EPSS (Exploit Prediction Scoring System) is a daily probability model maintained by FIRST.org. It estimates the likelihood a CVE will be exploited in production environments within the next 30 days, derived from real-world threat intelligence signals.
Blast Radius
yeswiki/yeswikiReal-time download stats are indexed for npm and PyPI packages. This vulnerability affects Packagist packages — download data is not available via public APIs for these ecosystems.
Description
Authenticated arbitrary file deletion in YesWiki <= 4.4.5
Summary
It is possible for any authenticated user, through the use of the filemanager to delete any file owned by the user running the FastCGI Process Manager (FPM) on the host without any limitation on the filesystem's scope.
This Proof of Concept has been performed using the followings:
- YesWiki v4.4.5 (
doryphore-devbranch, latest) - Docker environnment (
docker/docker-compose.yml) - Docker v27.5.0
- Default installation
Details
The vulnerability makes use of the filemanager that allows a user to manage files that are attached to a resource when they have owner permission on it. This part of the code is managed in tools/attach/libs/attach.lib.php
public function doFileManager($isAction = false)
{
$do = (isset($_GET['do']) && $_GET['do']) ? $_GET['do'] : '';
switch ($do) {
case 'restore':
$this->fmRestore();
$this->fmShow(true, $isAction);
break;
case 'erase':
$this->fmErase();
$this->fmShow(true, $isAction);
break;
case 'del':
$this->fmDelete();
$this->fmShow(false, $isAction);
break;
case 'trash':
$this->fmShow(true, $isAction);
break;
case 'emptytrash':
$this->fmEmptyTrash(); //pas de break car apres un emptytrash => retour au gestionnaire
// no break
default:
$this->fmShow(false, $isAction);
}
}
The fmErase() function doesn't sanitize or verify the path that has been provided by the user in any way. Thus allowing a malicious user to specify any arbitrary file on the filesystem and having it deleted through the use of unlink() (as long as the user that runs the process has permission to delete it).
public function fmErase()
{
$path = $this->GetUploadPath();
$filename = $path . '/' . ($_GET['file'] ? $_GET['file'] : '');
if (file_exists($filename)) {
unlink($filename);
}
}
In addition to this deletion accross all the filesystem through fmErase(), it is also possible to delete any file attached to an existing wiki page, for instance, if user A creates a page and attaches images/documents to it, they always get uploaded to the files/ directory. If user B (malicious), knows the path of the files he can also arbitrarly delete them. (fmDelete() is also impacted by this case)
PoC
1. Environnement setup
The following actions have been performed as a privileged user
First, let's create one user (in addition to the WikiAdmin user):
Restrict the edition of 'PagePrincipale' wiki page to administrators only:
2. Upload of a file on a resource not owned by our user
The following actions have been performed as a privileged user
Second, let's upload a media to this PagePrincipale wiki page:
Then view it in the page's filemanager:
We can confirm that our file has been uploaded to the files/ directory by directly looking at the yeswiki container:
3. Arbitrary deletion (in files/)
The following actions have been performed using an unprivileged user
Now, get the full path/name of the media in the files directory by opening it in a new tab:
Afterwards, we need an instance of filemanager to be accessible to our user so we need to create a page that we own, here is used the agenda and the creation of a new event:
Call the erase method on the PagePrincipale's uploaded media:
The media is now deleted from PagePrincipale (the button is shown when the attached media doesn't exist, it's an intended behaviour):
It has also disappeared from the files/ directory:
This behaviour can be applied to any file under the files/ directory.
4. Arbitrary deletion (in /tmp/)
The following actions have been performed using a privileged access
Finally, using the same user as the process running the app, we create a file under the /tmp directory:
The following actions have been performed using an unprivileged user
We can once again call the erase method using a relative path:
The file isn't here anymore:
Impact
This vulnerability allows any authenticated user to arbitrarly remove content from the Wiki resulting in partial loss of data and defacement/deteroriation of the website. In the context of a container installation of YesWiki without any modification, the 'yeswiki' files (for example .php) are not owned by the same user (root) as the one running the FPM process (www-data). However in a standard installation, www-data may also be the owner of the PHP files, allowing a malicious user to completely cut the access to the wiki by deleting all important PHP files (like index.php or core files of YesWiki).
Suggestion of possible corrective measures
-
Restrict the possible paths of
fmErase()to theupload_pathdirectory. -
Restrict the use of
fmErase()to trashed files only.
public function fmErase()
{
$path = $this->GetUploadPath();
$filename = $this->GetUploadPath() . '/' . basename(realpath(($_GET['file'] ? $_GET['file'] : ''))); //Sanitize file path
if (file_exists($filename) && preg_match('/trash\d{14}$/', $filename)) { //Make sure that the filename ends with trash and a date
unlink($filename);
}
}
- Make sure that any request to
fmErase()orfmDelete()originates from the owner of the resource to which the attachment is linked (asks a bit more than a few lines of code).
Affected Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| 🐘Packagist | yeswiki/yeswiki | all versions | 4.5.0 |
Detection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for yeswiki/yeswiki. O3's reachability analysis confirms whether the vulnerable code path is actually invoked in your application, so you act on real exposure instead of every transitive match.
Fix
Update yeswiki/yeswiki to 4.5.0 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms GHSA-43c9-gw4x-pcx6 is resolved across your whole dependency graph.
Workarounds
If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.
How O3 protects you
O3 pinpoints whether GHSA-43c9-gw4x-pcx6 is reachable in your code and exactly where to fix it, then blocks exploitation in production at runtime until the patched version is deployed.
Tailored to GHSA-43c9-gw4x-pcx6. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.
Frequently Asked Questions
Is GHSA-43c9-gw4x-pcx6 in your dependencies?
O3 detects GHSA-43c9-gw4x-pcx6 across Packagist dependencies and uses function-level reachability to confirm whether the vulnerable code path is actually reachable — not just present. No false positives.