Trash Can Fire: How the TYPO3 Recycler Turned into a Data Shredder
Jan 13, 2026·7 min read
Executive Summary (TL;DR)
The 'Recycler' (trash bin) in TYPO3 didn't check if you had permission to modify a specific table before letting you permanently delete records from it. It also got confused by records that were already 'soft-deleted,' effectively failing open on permission checks. Result: Low-privileged backend users could wipe out the entire site's database, including admin accounts and root pages.
A broken access control vulnerability in the TYPO3 CMS Recycler module allowed authenticated backend users to bypass table-level permissions and permanently delete arbitrary data. By exploiting logic flaws in how 'soft-deleted' records were handled, attackers could purge critical system tables, resulting in a catastrophic Denial of Service.
The Hook: The Janitor With the Nuclear Codes
In the world of Content Management Systems (CMS), the "Recycler" or "Trash Bin" is usually a boring, safe corner of the backend. It's the digital safety net where content editors go to retrieve that blog post they accidentally deleted before their morning coffee kicked in. It's supposed to be forgiving. It's supposed to be low-risk.
But in TYPO3, a framework known for its rigorous permission granularity, the Recycler turned out to be the ultimate weapon. CVE-2025-59022 isn't a complex buffer overflow or a fancy deserialization chain. It's a logic failure that gave the digital janitor the keys to the incinerator.
Here is the setup: You grant a junior editor access to the Recycler so they can manage their own mistakes. You restrict them so they can only edit blog posts (tx_news). You explicitly forbid them from touching system users (be_users) or core configurations. You sleep soundly, thinking your ACLs (Access Control Lists) are bulletproof.
Then, that junior editor sends a single AJAX request and permanently purges your Administrator account. Oops.
The Flaw: Logic Rot in the Trash Heap
To understand this vulnerability, you have to understand how TYPO3 handles deletion. Like many enterprise systems, TYPO3 uses "soft deletion." When you delete a page, it doesn't vanish; the database column deleted is set to 1. The Recycler module's job is to show these deleted=1 records and offer two choices: Restore (undelete) or Purge (hard delete).
The vulnerability stems from a catastrophic misalignment of two systems: Authorization and Context.
First, the DataHandler—the central engine for database writes—was asleep at the wheel. When receiving a command to permanently delete a record, it blindly assumed that if you reached that point, you must be allowed to do it. It neglected to call checkModifyAccessList($table), which is the specific function that checks if the current user group is actually allowed to modify the target table.
Second, and arguably funnier, was the "Ghost Problem." When TYPO3 checks permissions (e.g., "Is this user allowed to edit this page?"), it traverses the "Rootline" (the page tree). But standard permission checks filter out deleted records. So, when the Recycler asked, "Can User X manage this deleted record?", the permission system couldn't find the record in the active tree because... well, it was deleted.
Instead of failing secure (blocking access), the logic essentially shrugged. The traversal failed to validate the path, and the operation proceeded. It's the security equivalent of a guard saying, "I can't find your ID in the system because you're listed as 'fired', so go right ahead and enter the server room."
The Code: Diff or It Didn't Happen
The fix required patching the DataHandler to stop trusting the caller. Let's look at the critical logic gap in typo3/sysext/core/Classes/DataHandling/DataHandler.php.
The Vulnerable Logic (Conceptual):
public function deleteAction(string $table, int $uid, ...): void
{
// Proceed to delete without checking if the user owns this table
$this->deleteRecord($table, $uid);
}The Fix (v12/v13): In the patch, the maintainers force a hard stop if the user lacks table-specific modification rights. They also updated the permission checkers to handle the "Ghost Problem" by allowing traversal of deleted nodes.
// File: typo3/sysext/core/Classes/DataHandling/DataHandler.php
public function deleteAction(string $table, int|array $uidOrRow, bool $noRecordCheck = false, bool $forceHardDelete = false): void
{
// ... (snip) ...
// THE FIX: Explicitly verify the user has access to modify this specific table.
// If $noRecordCheck is false (default for Recycler), this gate drops.
if (!$noRecordCheck && !$this->checkModifyAccessList($table)) {
$this->log(
$table,
0,
SystemLogDatabaseAction::DELETE,
null,
SystemLogErrorClassification::USER_ERROR,
'Cannot delete "{table}:{uid}" without permission',
null,
['table' => $table, 'uid' => $uid]
);
return;
}
// ... (proceed to delete)
}They also had to patch BackendUtility::BEgetRootLine and BackendUserAuthentication::isInWebMount to accept a new flag that says, "Yes, I know it's deleted, check the permissions anyway." Without this, the system literally couldn't "see" the deleted items to verify ownership.
The Exploit: Taking Out the Trash (Permanently)
Exploiting this is trivially easy if you have a compromised or malicious low-level account. The Recycler module operates via AJAX controllers. We don't need a complex binary payload; we just need a valid session cookie and a browser developer console (or Burp Suite).
The Attack Scenario:
- Recon: Log in as
LowPrivUser. Confirm you have access to the Recycler module. You don't need admin rights; you just need the module enabled. - Target Selection: You want to cause maximum chaos. The
be_userstable (backend admins) orsys_template(TypoScript site configuration) are prime targets. Let's say we want to delete the main Administrator (UID 1). - The Payload: The Recycler expects a command to delete records. It should only work for stuff you deleted, but thanks to the missing table check, we can feed it anything.
[!WARNING] This is a hypothetical attack chain for educational purposes. Do not execute this on live environments.
POST /typo3/ajax/recycler/delete HTTP/1.1
Host: target-typo3-site.com
Cookie: be_typo_user=...
Content-Type: application/json
{
"table": "be_users",
"uid": 1
}The Result:
The DataHandler receives the request.
- Check 1: "Is the user authenticated?" Yes.
- Check 2: "Is
be_usersin their allowed modify list?" SKIPPED (The vulnerability). - Check 3: "Is the record deleted?" If the admin account wasn't already soft-deleted, the exploit might require a two-step process (soft-delete first via another vector, or relying on
forceHardDeleteparameters if exposed), but in many vulnerable versions, the validation logic simply collapses.
The database executes DELETE FROM be_users WHERE uid=1. The main admin is gone. The site is effectively headless.
The Impact: Scorched Earth
Why is this a High severity (7.1) and not Critical (9.0+)? Mostly because it requires an authenticated account. However, inside an organization, the impact is devastating. This is an Availability nightmare.
An insider threat or a compromised editor account can:
- Wipe Administrative Access: Delete all
be_usersexcept their own (or even their own, for pure nihilism). - Brick the Frontend: Delete
sys_template(root TypoScript records) orpages(root page tree). The public website will immediately throw 500 errors or 404s. - Destroy Business Data: Purge
tt_address,fe_users(customer data), or shop orders if extensions likeext:cartorext:newsare used.
Because this is a Hard Delete (SQL DELETE), there is no "Undo" button in the CMS. Unless you have recent, cold offline database backups, the data is gone forever. It is the digital equivalent of setting the archives on fire.
The Fix: Patch or Perish
The TYPO3 security team released a coordinated patch across five major versions on January 13, 2026. This is not a configuration fix; you must update the core code.
Remediation Steps:
- Composer Update: If you are running a modern TYPO3 setup, run:
composer update "typo3/cms-*" --with-all-dependencies - Verify Version: Ensure your
typo3/cms-corepackage matches the fixed versions below.
Fixed Versions:
- v14.0.2
- v13.4.23
- v12.4.41
- v11.5.49 (ELTS)
- v10.4.55 (ELTS)
Emergency Mitigation:
If you cannot deploy the patch immediately, you must revoke access to the Recycler module for everyone except the most trusted Super Admins. Go to Backend Groups -> Access Lists -> Modules and uncheck Recycler.
Official Patches
Fix Analysis (2)
Technical Appendix
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:NAffected Systems
Affected Versions Detail
| Product | Affected Versions | Fixed Version |
|---|---|---|
TYPO3 CMS TYPO3 | 14.0.0 - 14.0.1 | 14.0.2 |
TYPO3 CMS TYPO3 | 13.0.0 - 13.4.22 | 13.4.23 |
TYPO3 CMS TYPO3 | 12.0.0 - 12.4.40 | 12.4.41 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-862 |
| Attack Vector | Network (Ajax) |
| CVSS v4.0 | 7.1 (High) |
| Impact | High Availability Loss (Data Destruction) |
| Privileges Required | Low (Authenticated Backend User) |
| Exploit Status | Logic Flaw (Trivial to Script) |
| Vendor | TYPO3 |
MITRE ATT&CK Mapping
The software does not perform an authorization check when an actor attempts to access a resource or perform an action.
Known Exploits & Detection
Vulnerability Timeline
Subscribe to updates
Get the latest CVE analysis reports delivered to your inbox.