Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
drupal-htmx-attr — Drupal 11.4.8 - High - Remote - XSS - AttributeXss still allows HTMX attrs | Kitploit
Tools/GitHubGitHub/abraxas/drupal-htmx-attr
Vulnerability AnalysisExploitationWeb Application ExploitationWeb SecurityPenetration TestingLabs & Practice
GitHubabraxas/drupal-htmx-attr

drupal-htmx-attr

Drupal 11.4.8 - High - Remote - XSS - AttributeXss still allows HTMX attrs

View Repository
4 days agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

Abraxas Labs - drupal-htmx-attr

abraxaslabs.tech  ·  github.com/abraxas  ·  @abraxas_null  ·  [email protected]  ·  drupal-htmx-attr

drupal-htmx-attr

Class: Stored XSS Reach: Remote

Drupal core 11.4.8 (61044508) - Drupal

SA-CORE-2026-011 closed HTMX attrs in Xss::attributes(). Link and menu attributes go through AttributeXss::sanitizeAttributes, and that skip list still only drops style and on*.

A content editor who can set a Link field (or a menu link) can store hx-on-click or data-hx-on-click. Standard plus BigPipe loads core/htmx. When an admin or any other viewer opens that node and clicks the link, HTMX runs the stored JS in the site origin.

IDno CVE yet
ClassStored XSS (HTMX event attrs)
ReachRemote (authenticated Link field / menu writer; victim views and clicks)
CWECWE-79
CVSSHigh: 8.7 CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:N
ProductDrupal core
Affected11.4.8 (61044508071749629aaf3380aa85971e94df9e84)
Authauthenticated user who can write a Link field (or menu link). Victim views the page and clicks.
LicenseGNU Affero GPL v3.0
Lab127.0.0.1 only

What an attacker can do

Writer: a content editor who can set link options.attributes (Link field, menu link, JSON:API). Victim: anyone whose page loads HTMX (Standard + BigPipe loads core/htmx), including a site admin who clicks the link.

PrivilegeMethod / pathKindLab-proven or inferred
Persist HTMX event attrs on a linkPOST /jsonapi/node/article with field_link.options.attributes.hx-on-click and data-hx-on-clickIntegrity of stored fieldLab-proven. JSON:API 201, stored attrs still contain hx-on-click
Print those attrs on the node <a>LinkFormatter -> AttributeXss::sanitizeAttributesIntegrity of HTMLLab-proven. GET /node/1 HTML contains hx-on-click and the marker window['DRUPAL-HTMX-ATTR-WITNESS']=1
Run that JS in the victim origin when they clickHTMX binds hx-on-*Integrity of victim sessionInferred from HTMX + the page loading core/htmx. Lab did not drive a browser click
Act as the viewer (session cookie, admin UI clicks)Same stored XSSIntegrity of victim sessionInferred. Lab stops at the attribute remaining in HTML
Negative: Xss::filterXss::filter('<a ... hx-on-click=...>')ClosedLab-proven closed. xss_keeps_hx=False
Unauthenticated write of the linkJSON:API without a sessionClosedLab logged in as uid 1 first. A stranger with no account cannot set the field
PHP RCE / LPEn/aClosedThis leftover is browser JS, not PHP on the server

Same pin leftover: Move Block sibling markup.

How I found it

I pinned drupal/drupal 11.4.8 after SA-CORE-2026-011. Five hunts: XSS/HTMX, file/MIME/oEmbed, JSON:API/unserialize/SQLi, auth/CSRF/Host, REST/media/Views. JSON:API access, EntityQuery IN keys (SA-004), serialized-field POI (SA-005), and rebuild.php Host (SA-007) stay patched. The HTMX skip list landed in Xss.php only.

$skip = (
  in_array($attribute_name, ['style', 'srcdoc']) ||
  str_starts_with($attribute_name, 'on') ||
  str_starts_with($attribute_name, 'data-hx') ||
  str_starts_with($attribute_name, 'hx') ||
  str_starts_with($attribute_name, '-') ||
  strlen($attribute_name) > 96
);

AttributeXss.php leftover:

$skip = (
  $attribute_name == 'style' ||
  str_starts_with($attribute_name, 'on') ||
  str_starts_with($attribute_name, '-') ||
  strlen($attribute_name) > 96
);

Callers include LinkFormatter.php and MenuLinkContent::getUrlObject().

Wrong turns already recorded: treating Xss::filter as the leftover (it is the control); unauth JSON:API write; PHP RCE; a reverse shell. Theatre. The oracle is the attr remaining on the node HTML plus core/htmx loaded.

Lab

python3 drupal-htmx-attr-Abraxas-Labs.py

or

cd lab
./run.sh

Target only http://127.0.0.1:19480. Live drupal:11.4.8-apache, Standard profile, JSON:API write enabled for the lab. Compose project drupal-htmx-attr.

SUCCESS drupal-htmx-attr how=live write=jsonapi nid=1 hx-on-click=kept jsonapi-stored=1 xss-filter=stripped htmx=loaded marker=1 version=11.4.8 DRUPAL-HTMX-ATTR-WITNESS

The fix

Copy the hx / data-hx / srcdoc denylist into AttributeXss. Fold it into Xss as the class docblock already says.

References

  • github.com/drupal/drupal tag 11.4.8 (61044508071749629aaf3380aa85971e94df9e84)
  • AttributeXss.php · Xss.php
  • Nearby patched: SA-CORE-2026-011
  • Same pin: drupal-move-block-markup
  • CWE-79

License

GNU Affero GPL v3.0. See LICENSE. Loopback lab only. No warranty.

Download Tool