Feb 19, 2026·6 min read·4 visits
Authenticated users can force values into restricted fields (e.g., 'hidden', 'starttime') by abusing the `defVals` parameter. The vulnerability exists because these default values were treated as trusted system configuration rather than untrusted user input.
A sophisticated Access Control Bypass in TYPO3 CMS allows authenticated backend users to circumvent field-level permissions. By manipulating the `defVals` parameter during record creation, attackers can inject values into restricted fields (like visibility flags or access groups), effectively bypassing the `checkFieldEditAccess` validation logic meant to secure sensitive metadata.
In the world of Content Management Systems, usability often clashes with security. TYPO3, a heavyweight enterprise CMS, offers a convenient feature called defVals (Default Values). This mechanism allows the backend interface to pre-populate form fields when a user creates a new record. Think of it as a helpful assistant filling in the boring parts of a form for you.
However, in security, every helpful assistant is a potential double agent. The vulnerability here isn't that default values exist; it's how the system decided to trust them. In affected versions of TYPO3, the system failed to distinguish between "defaults suggested by the system configuration" and "defaults injected by a potentially malicious user via the URL."
This creates a classic "Trojan Horse" scenario. The gatekeeper (Access Control List) checks the main data payload rigorously. But the defVals payload? That was ushered in through the VIP entrance, bypassing the standard field-level permission checks entirely. If you know how to ask, you can tell the system: "I want to create a new article, and oh, by the way, the default state for 'is_published' is definitely 'true'," even if you aren't allowed to touch that button.
To understand this bug, you have to look at the EditDocumentController and its interaction with TYPO3's core engine, the DataHandler (often referred to historically as TCEmain). When a user submits a request to create a record, the controller prepares the data.
The fatal flaw was a direct assignment of user input to a trusted property. The controller took the defVals array from the request and assigned it directly to $dataHandler->defaultValues. In the TYPO3 architecture, values inside $dataHandler->defaultValues are historically treated as if they came from trusted TSconfig (TypoScript Configuration) or internal system calls.
Because of this implicit trust, when the DataHandler processes the new record, it applies the default values outside the rigorous checkFieldEditAccess loop that sanitizes standard user input. The system assumes, "Well, if this value is in the defaults array, the administrator must have configured it, so it's safe." It didn't account for the fact that the "administrator" in this case was actually a low-privileged user manually tweaking URL parameters.
Let's look at the code. This is a textbook example of why input validation placement matters. In the vulnerable version of EditDocumentController, the code looked something like this (simplified for clarity):
// VULNERABLE CODE
// Taking user input and assigning it to a trusted property
$dataHandler->defaultValues = $this->defVals ?? [];
$dataHandler->process_datamap();The fix is subtle but changes the entire data flow. Instead of letting defVals sit in the VIP defaultValues property, the patch forces these values into the standard data map ($this->data). This forces them to go through the standard validation grinder.
// PATCHED CODE (Simplified Logic)
if (is_array($this->defVals[$tableName] ?? null)) {
foreach ($records as $uid => $_) {
// Only apply to NEW records
if (str_contains((string)$uid, 'NEW')) {
// Merge the "defaults" into the main data array
// This subjects them to standard ACL checks later
$this->data[$tableName][$uid] = array_merge(
$this->defVals[$tableName],
$this->data[$tableName][$uid]
);
}
}
}By merging the values into $this->data, the DataHandler no longer sees them as "magical system defaults." It sees them as "user is trying to set field X to value Y." Consequently, if the user lacks the permission to edit field X (e.g., it's in their exclude fields list), the DataHandler will correctly reject the change.
Let's construct a realistic attack scenario. Imagine you are a standard "Editor" in a corporate TYPO3 installation. You have permission to create tt_content elements (text, images), but you are strictly forbidden from publishing them. The hidden field (which controls visibility) is in your "exclude fields" list—you can't see it, and you can't toggle it.
The Goal: Publish a post immediately, bypassing the "Reviewer" approval step.
The Attack:
&defVals[tt_content][hidden]=0.The full request might look like this:
GET /typo3/record/edit?edit[tt_content][1]=new&defVals[tt_content][header]=Hacked&defVals[tt_content][hidden]=0
The Result:
The backend renders the form (or processes the save). Because the hidden=0 value was passed as a defVal, it initializes the record as visible. Since you (the Editor) don't have permission to change the hidden field, the form won't even show you the checkbox to turn it back off. But it doesn't matter—the damage is done. The record is created with hidden=0 (Visible) in the database. You've successfully bypassed the editorial workflow.
This isn't an RCE (Remote Code Execution). You aren't going to be dropping webshells or dumping the database passwords with this alone. However, the Integrity impact is High.
In complex TYPO3 environments, permissions are granular for a reason. "Exclude fields" are used to prevent lower-level admins from:
fe_group), potentially exposing private intranet content to the public internet.starttime, endtime, sys_language_uid).An attacker could use this to deface the site by making hidden draft content visible, or disrupt operations by assigning content to the wrong language or access group. It turns the meticulous permission model of TYPO3 into a mere suggestion.
The remediation is straightforward: Apply the official patches provided by the TYPO3 maintenance team. The vulnerability is patched in versions 10.4.55 ELTS, 11.5.49 ELTS, 12.4.41 LTS, 13.4.23 LTS, and 14.0.2.
If you cannot patch immediately, you are in a tight spot. There is no clean configuration workaround because disabling defVals entirely might break legitimate backend functionality (like the "New Content" wizard).
WAF Mitigation (Risky):
You could theoretically configure a WAF to block requests containing defVals parameters that target known sensitive fields (e.g., regex blocking defVals.*hidden), but this is a game of whack-a-mole. You will likely miss other sensitive fields or break valid workflows. The only real fix is the code update.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
TYPO3 CMS TYPO3 | 10.0.0 - 10.4.54 | 10.4.55 ELTS |
TYPO3 CMS TYPO3 | 11.0.0 - 11.5.48 | 11.5.49 ELTS |
TYPO3 CMS TYPO3 | 12.0.0 - 12.4.40 | 12.4.41 LTS |
TYPO3 CMS TYPO3 | 13.0.0 - 13.4.22 | 13.4.23 LTS |
TYPO3 CMS TYPO3 | 14.0.0 - 14.0.1 | 14.0.2 |
| Attribute | Detail |
|---|---|
| CWE | CWE-863 (Incorrect Authorization) |
| CVSS v3.1 | 6.5 (Medium) |
| Attack Vector | Network (Authenticated) |
| Impact | Integrity (High) |
| EPSS Score | 0.00011 (Low Probability) |
| Exploit Status | No Public Exploit (POC only) |
When an application does not properly check if a user is authorized to access or modify specific data fields (like 'exclude fields' in TYPO3), attackers can bypass restrictions.