Drupal: SA-CORE-2026-014, critical remote code execution vulnerability in Field UI

Updated as new information comes in (D8 and D9 patch at the end of the page)

The Drupal security team announced it on October 12 with PSA-2026-10-12: the critical core security update was released on Wednesday, October 14, 2026, with advisory SA-CORE-2026-014. It is a remote code execution vulnerability, exploitable without authentication in at least one known scenario. Apply it right away.

The vulnerability in brief

  • Identifiers: SA-CORE-2026-014, CVE-2026-108097.
  • Type: remote code execution (RCE).
  • Severity: "Critical", 19/25 (AC:Basic/A:None/CI:All/II:All/E:Theoretical/TD:Default).
  • Affected module: Field UI (field_ui), the core module that provides the field management interface.

Core alone does not directly expose the vulnerability, but the advisory states that several serious exploitation paths exist through contrib modules, at least one of which requires no authentication. Custom code can also expose the vulnerable functionality. In other words: even if your site "only" uses core, don't bet on not being exposed.

Note that the final rating is more severe than the one announced in the PSA: attack complexity goes from "Complex" to "Basic", and the vulnerability affects default or common configurations.

Affected versions

  • 8.9.0 to 10.6.18;
  • 11.0.0 to 11.3.18;
  • 11.4.0 to 11.4.9;
  • Drupal 12 alpha and beta versions prior to 12.0.0-beta2.

The range goes all the way back to Drupal 8.9: end-of-life branches (Drupal 8, Drupal 9, Drupal 10 before 10.6, Drupal 11 before 11.3) are therefore vulnerable, but will not receive a fix.

Fixed versions

  • Drupal 11.4.x: 11.4.10;
  • Drupal 11.3.x: 11.3.19;
  • Drupal 10.6.x: 10.6.19.

To update:

composer update "drupal/core-*" --with-dependencies
git diff composer.lock   # should only show drupal/core* packages

Then check the version actually installed:

drush status --field=drupal-version

The advisory warns that packages may take a little while to become available: if Composer can't find the new version yet, wait 30 to 45 minutes before trying again.

Two more fixes in the same release

These versions don't fix just one vulnerability. They also ship two other advisories published the same day, less severe, applied automatically by the update:

  • SA-CORE-2026-015 (cross-site scripting, "Moderately critical" 13/25, CVE-2026-108515, a proof of concept exists): link HTML attribute filtering (Link module) now also strips HTMX attributes (hx-* and data-hx-*), which could be used for cross-site scripting now that HTMX is in core. All versions since 8.9.0 are affected. Side effect: an hx-* attribute deliberately added to a link will be removed;
  • SA-CORE-2026-016 (cross-site scripting, "Moderately critical" 12/25, CVE-2026-108514): tooltips in the Navigation module (the new admin toolbar) rendered their text as HTML; they now render it as plain text. Only sites with this module enabled are affected (versions since 10.3.0), and the attacker must be able to enter HTML tags with certain data-* attributes or administer menus. Side effect: intentional HTML in a tooltip will be displayed as is.

Versions 10.6.19 and 11.3.19 also move CKEditor 5 to 47.6.3-drupal.1, a version maintained by Drupal: one more thing to check during QA on those two branches.

What about contrib modules

Two contrib advisories published the same day fix the same code as core, copied into those projects:

  • SA-CONTRIB-2026-218, Entity List: remote code execution, "Critical" 19/25, CVE-2026-108099, same text and same rating as SA-CORE-2026-014. The module ships a copy of the Field UI table, fixed the same way. Update to 3.0.10;
  • SA-CONTRIB-2026-219, Gin admin theme: cross-site scripting, "Moderately critical" 13/25, CVE-2026-110738. Gin has its own tooltips, fixed like those of the Navigation module (SA-CORE-2026-016). Update to 4.1.4 (Gin 4) or 5.0.16 (Gin 5).

Since Gin is very widespread, it is probably installed on a good share of your sites: you might as well include it in the same update as core.

composer update drupal/gin drupal/entity_list --with-dependencies

Until you can update: uninstall Field UI

If you can't update immediately, the advisory states that uninstalling the Field UI module protects the site until the update is done:

drush pm:uninstall field_ui -y

Field UI is only used for the field administration interface: uninstalling it deletes neither the fields nor their data. On a site whose config is under version control, make sure not to export this uninstall by mistake, or re-enable the module once the fix is in place.

This workaround only covers SA-CORE-2026-014: the two other vulnerabilities are only fixed by the update.

WARNING: disabling the module can trigger cascading config deletions, it happened to me; read carefully what the command outputs before confirming.

Am I exposed?

The fix concerns how Field UI determines the region of each row in its tables ("Manage display", "Manage form display"): until now, it called a function referenced in the render array without checking that it was allowed. Core alone does not let outside data reach that point; the risk comes from contrib modules or custom code that would allow it. A few checks to run, in addition to the update (which remains the only real protection):

  • Prioritize: patch first the public sites that have lots of contrib modules and forms open to anonymous visitors.
  • Review your custom code: look for uses of the field_ui_table element and the #region_callback property.

    grep -rn "field_ui_table\|#region_callback" web/modules/custom web/themes/custom

    Common contrib modules use it too (field_group, ui_patterns_ui): their logic mirrors core's, and the fix shouldn't change how they work.

  • Keep an eye out over the following days:
    • in access logs, unusual anonymous POST requests, especially with parameters that look like Drupal render properties (starting with #, or %23 once encoded);
    • in the Drupal log (watchdog), PHP errors coming from FieldUiTable;
    • on disk, recently created or modified PHP files in sites/*/files or at the site root.
# PHP files created or modified in the last 7 days in public files
find web/sites/*/files -name "*.php" -mtime -7

# Recent Field UI related errors in the Drupal log
drush watchdog:show --severity=Error --count=200 | grep -i fielduitable

If any of these checks turns up something suspicious, the site must be treated as compromised: updating is no longer enough, you need to investigate and restore from a clean backup.

Links

What about an end-of-life site?

For sites still running a version that no longer receives fixes, a developer has published an unofficial patch for Drupal 9.5.11. It applies to FieldUiTable.php the same change as the official release.

I haven't tested it: it is neither validated nor maintained by the Drupal security team, it only covers SA-CORE-2026-014 (not the two other vulnerabilities), and it is no substitute for upgrading to a supported version. Review it before applying it, at your own risk.

And on Drupal 8.9?

The patch above also applies to Drupal 8.9.20 (checked with a patch --dry-run, with a slight line offset). It applies from the core/ directory, since its paths are relative to it.

Be careful though: it uses array_key_first(), which only exists as of PHP 7.3. Drupal 8.9 sometimes still runs on an older PHP. Here is a variant of the same change, without ?? or array_key_first(), to apply from the docroot (the directory containing core/) with patch -p1.

I applied this variant in production on a Drupal 8.9.20 site (PHP 7.4) due to be decommissioned: the patch applies without changes, the site responds normally, no errors showed up in the logs, and the "Manage display" and "Manage form display" pages still render. That's a single site, so no guarantee for yours.

diff --git a/core/modules/field_ui/src/Element/FieldUiTable.php b/core/modules/field_ui/src/Element/FieldUiTable.php
--- a/core/modules/field_ui/src/Element/FieldUiTable.php
+++ b/core/modules/field_ui/src/Element/FieldUiTable.php
@@ -67,7 +67,13 @@
           unset($list[$name]);
 
           // Determine the region for the row.
-          $region_name = call_user_func_array($row['#region_callback'], [&$row]);
+          // SA-CORE-2026-014 : la region est lue dans la valeur de l'element,
+          // plus aucun callable n'est appele depuis le tableau de rendu.
+          $region_name = isset($row['region']['#value']) ? $row['region']['#value'] : '';
+          if (!isset($regions[$region_name])) {
+            $region_keys = array_keys($regions);
+            $region_name = isset($regions['hidden']) ? 'hidden' : reset($region_keys);
+          }
 
           // Add the element in the tree.
           $target = &$trees[$region_name][''];

To apply it, keeping the backup outside the docroot: a FieldUiTable.php.orig copy left next to the file could be served as is by the web server.

mkdir -p ~/backup-sa-core-2026-014
cp core/modules/field_ui/src/Element/FieldUiTable.php ~/backup-sa-core-2026-014/FieldUiTable.php.orig
patch --dry-run -p1 < SA-CORE-2026-014-d8.patch && patch -p1 < SA-CORE-2026-014-d8.patch
php -l core/modules/field_ui/src/Element/FieldUiTable.php
drush cr

Same caveats as above: unofficial, review it, and only to buy time on a site that is going away or being migrated. And if the site is deployed with Composer, a composer install will overwrite the change: declare it in the patches section of composer.json.

Written by Kevin Gautreau — freelance PHP/Drupal developer & trainer in Auvergne, France. get in touch

Comments (0)