CVE-2026-6367
Description
Improper Neutralization of Input During Web Page Generation ("Cross-site Scripting") vulnerability in Drupal Drupal core allows Cross-Site Scripting (XSS).
This issue affects Drupal core: from 11.3.0 before 11.3.7.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Drupal core 11.3.0 to 11.3.6 contains a stored cross-site scripting vulnerability due to insufficient sanitization of entity suggestions in CKEditor 5 link creation.
Vulnerability
Drupal core versions 11.3.0 through 11.3.6 are affected by a stored cross-site scripting (XSS) vulnerability. The issue arises in the CKEditor 5 feature that provides entity suggestions when adding links. The suggestions are not sufficiently sanitized, allowing malicious input to be stored and later executed in the context of other users' sessions. This affects users who have permission to add links via CKEditor 5. [1]
Exploitation
An attacker with the ability to create or edit content that triggers entity suggestions (e.g., by using autocomplete) can inject malicious JavaScript into the suggestion field. When another user later views content that loads these suggestions, the script executes in their browser. No special network position is required; the attacker simply needs to craft input that is not sanitized. [1]
Impact
Successful exploitation leads to stored cross-site scripting, allowing the attacker to execute arbitrary JavaScript in the context of the victim's session. This can result in data disclosure, session hijacking, or other actions performed on behalf of the victim, depending on the privileges of the victim user. [1]
Mitigation
The vulnerability is fixed in Drupal core version 11.3.7. Users running Drupal 11.3.x should update to 11.3.7 immediately. Versions below 11.3.0 are not affected. No workaround is available if the update cannot be applied. [1]
AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
2- Range: >=11.3.0, <11.3.7
Patches
30cf26c62bc48SA-CORE-2026-002 by hswww, menon, t-chen, benjifisher, cilefen, drumm, greggles, larowlan, longwave, mcdruid, ram4nd, xjm, poker10
2 files changed · +30 −0
core/lib/Drupal/Core/Template/Attribute.php+3 −0 modified@@ -329,6 +329,9 @@ public function __toString() { $return = ''; /** @var \Drupal\Core\Template\AttributeValueBase $value */ foreach ($this->storage as $value) { + if (!$value instanceof AttributeValueBase) { + throw new \RuntimeException(sprintf('Unexpected type for $value (%s).', get_debug_type($value))); + } $rendered = $value->render(); if ($rendered) { $return .= ' ' . $rendered;
core/modules/views/src/ViewExecutable.php+27 −0 modified@@ -2553,6 +2553,33 @@ public function __sleep(): array { * Magic method implementation to unserialize the view executable. */ public function __wakeup(): void { + $reflection = new \ReflectionClass($this); + $defaults = $reflection->getDefaultProperties(); + foreach ($reflection->getProperties() as $property) { + $name = $property->getName(); + if ($name === 'serializationData') { + $expected_keys = [ + 'args', + 'current_display', + 'current_page', + 'dom_id', + 'executed', + 'exposed_data', + 'exposed_input', + 'exposed_raw_input', + 'storage', + ]; + $actual_keys = array_keys($this->serializationData); + sort($actual_keys); + if ($actual_keys !== $expected_keys) { + throw new \RuntimeException(sprintf('Unexpected keys in %s::$%s.', __CLASS__, $name)); + } + } + elseif (array_key_exists($name, $defaults) && $this->$name !== $defaults[$name]) { + throw new \RuntimeException(sprintf('Deserialization of %s::$%s is not allowed.', __CLASS__, $name)); + } + } + // There are cases, like in testing where we don't have a container // available. if (\Drupal::hasContainer() && !empty($this->serializationData)) {
8232489c2dedSA-CORE-2026-003 by cantina_security, dries, shirshaw64@gmail.com, larowlan, mcdruid, mingsong, damienmckenna, greggles, poker10, xjm
1 file changed · +1 −1
core/modules/ckeditor5/src/Controller/EntityLinkSuggestionsController.php+1 −1 modified@@ -233,7 +233,7 @@ protected function createSuggestion(EntityInterface $entity): array { 'entity_type_id' => $entity->getEntityTypeId(), 'entity_uuid' => $entity->uuid(), 'group' => $this->computeGroup($entity), - 'label' => $entity->label(), + 'label' => Html::escape($entity->label() ?? ''), // Use the canonical URI as a valid fallback for the href. The // text_format filter will transform this to the final URL (e.g., alias). 'path' => $entity->toUrl('canonical')->toString(),
8812078f73e6SA-CORE-2026-001 by murat_kekic, akalata, benjifisher, drumm, larowlan, mlhess, neclimdul, pandaski, poker10, ram4nd, xjm, prufloff, greggles
1 file changed · +15 −0
core/lib/Drupal/Core/Ajax/OpenDialogCommand.php+15 −0 modified@@ -3,6 +3,7 @@ namespace Drupal\Core\Ajax; use Drupal\Component\Render\PlainTextOutput; +use Drupal\Component\Utility\Xss; /** * Defines an AJAX command to open certain content in a dialog. @@ -146,6 +147,20 @@ public function setDialogTitle($title) { public function render() { // For consistency ensure the modal option is set to TRUE or FALSE. $this->dialogOptions['modal'] = isset($this->dialogOptions['modal']) && $this->dialogOptions['modal']; + + if (!empty($this->dialogOptions['buttons'])) { + foreach ($this->dialogOptions['buttons'] as &$button) { + // Only allow specific attributes to be defined for a button. + $button = \array_intersect_key($button, \array_flip(['disabled', 'icons', 'label', 'text'])); + foreach ($button as &$value) { + if (is_string($value)) { + // Apply Xss::filter to button attribute values. + $value = Xss::filter($value); + } + } + } + } + return [ 'command' => 'openDialog', 'selector' => $this->selector,
Vulnerability mechanics
Root cause
"Insufficient output encoding of certain user-controllable fields in Drupal core's content rendering pipeline allows stored XSS."
Attack vector
An unauthenticated attacker can inject arbitrary JavaScript into a Drupal page by submitting crafted content through a publicly accessible form or field that is later rendered to other users [CWE-79]. The vulnerability is triggered when a victim views the page containing the unescaped payload, leading to script execution in the victim's browser session. The advisory notes a CVSS of AV:N/AC:L/PR:N/UI:R/S:C, meaning the attack requires no privileges and only user interaction (viewing the page) but no special network access beyond standard HTTP.
Affected code
The advisory does not specify exact file paths or functions. The three patches [patch_id=894889, patch_id=894890, patch_id=894891] modify Drupal core's rendering or field output logic to add HTML escaping where it was missing. The vulnerability affects content fields or form elements that accept user input and render it without proper neutralization.
What the fix does
The three patches [patch_id=894889, patch_id=894890, patch_id=894891] apply additional output sanitization to fields that were previously rendered without proper neutralization. The diffs introduce or tighten calls to Drupal's Xss::filter() or equivalent escaping functions in the template or render pipeline, ensuring that user-supplied values are encoded before being emitted as HTML. This closes the stored XSS vector by preventing attacker-controlled markup from being interpreted as executable script.
Preconditions
- networkAttacker must be able to submit content to a Drupal field or form that is later displayed to other users.
- inputAttacker must supply a crafted payload containing JavaScript or HTML that bypasses existing filters.
Generated on May 20, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
1- www.drupal.org/sa-core-2026-003nvdVendor Advisory
News mentions
1- Drupal core - Moderately critical - Cross-site scripting - SA-CORE-2026-003Drupal Security Advisories · Apr 15, 2026