kostask
10/15/2026, 7:21 AMkostask
10/15/2026, 7:21 AM--- a/core/modules/field_ui/src/Element/FieldUiTable.php
+++ b/core/modules/field_ui/src/Element/FieldUiTable.php
@@ -69,7 +69,10 @@ class FieldUiTable extends Table {
// Determine the region for the row.
- $region_name = call_user_func_array($row['#region_callback'], [&$row]);
+ $region_name = $row['region']['#value'] ?? '';
+ if (!isset($regions[$region_name])) {
+ $region_name = isset($regions['hidden']) ? 'hidden' : array_key_first($regions);
+ }
The rest of the release is the version bump plus small fixes for the other two advisories: two lines in link/src/AttributeXss.php and a change to navigation/js/tooltip.js.
What the vulnerable code did
FieldUiTable is the field_ui_table render element, the draggable table on the “Manage fields / Manage display / Manage form display” pages. During pre-render, it looped over every row and called whatever was in that row’s #region_callback property using a bare call_user_func_array().
This is my reading of the diff, not something the advisory states: that call bypassed Drupal’s trusted-callback protection. Since 8.8, the render system only runs callbacks like #pre_render and #lazy_builder if they are explicitly marked safe through TrustedCallbackInterface. This hardening exists to stop render arrays built from untrusted data from becoming “call any PHP function” gadgets. The #region_callback key was handled by Field UI’s own code instead of the render system, so that protection never applied to it. It’s probably no coincidence that the affected range starts at 8.9.0.
In practice, the dangerous ingredient is this: if any code on the site lets attacker-influenced data end up as a field_ui_table render array, the attacker controls which function gets called. Core never does that, which is why core alone isn’t exploitable. A contributed module or custom code that renders arrays derived from user input, form state, or deserialized data could provide that path. It also explains the mitigation: with field_ui uninstalled, the field_ui_table element type doesn’t exist, so the callback can never be reached.
How it was fixed
The callback mechanism is removed entirely rather than wrapped in a trusted-callback check. The region now comes straight from the row’s region form element value and is validated against the table’s declared #regions. Anything unknown falls back to hidden, or the first region if there’s no hidden one. This is essentially what core’s only callback, EntityDisplayFormBase::getRowRegion(), already did, so core’s own pages behave the same as before.
What this means for your sites
There’s a side effect to check. Any contributed or custom module that sets its own #region_callback on Field UI rows will now be silently ignored. Modules that add custom regions or layout logic to the Manage display screens are the likeliest to rely on this. After updating, it’s worth opening the Manage display and Manage form display pages on a few bundles and confirming that field placement and dragging still behave correctly.
To audit your own code, search the custom modules and themes for field_ui_table and #region_callback. If you find custom code building field_ui_table elements, look closely at whether any part of those arrays can come from request data, stored config editable by lower-privileged users, or unserialize(). That’s exactly the kind of “custom code may also expose the vulnerable functionality” the advisory warns about. The safest course is still simply to update, since the patched code no longer calls anything from the render array at all.