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
element-ics-javascript — Element Web v1.12.29 - High - Remote - XSS - Univention ICS navigation.json link becomes a javascript: menu href | Kitploit
Tools/GitHubGitHub/abraxas/element-ics-javascript
Vulnerability AnalysisExploitationWeb Application ExploitationWeb SecurityPenetration Testing
GitHubabraxas/element-ics-javascript

element-ics-javascript

Element Web v1.12.29 - High - Remote - XSS - Univention ICS navigation.json link becomes a javascript: menu href

View Repository
3 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 - element-ics-javascript

abraxaslabs.tech  ·  github.com/abraxas  ·  @abraxas_null  ·  [email protected]  ·  element-ics-javascript

element-ics-javascript

Element Web v1.12.29 - Element / New Vector

Class: XSS Reach: Remote

The Univention banner module fetches ICS navigation.json, accepts each entry's link as z.string() with no scheme check, and Menu.tsx puts that string on a styled <a href>. Static menu config uses z.url() for link_url. The ICS path does not. URL preview on the same pin already rejects javascript: (previewFromBundle, GHSA-9r5h). This is not default app.element.io. It needs modules/banner with menu.type univention, plus an ICS the deploy trusts.

Anyone who can change that navigation.json plants javascript: or data:. A signed-in user who opens the banner menu and clicks the item runs script on the Element origin.

IDno CVE yet
CWECWE-79 / CWE-20
CVSSMedium: 6.8 CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:U/C:H/I:H/A:N
ProductElement Web
Affectedv1.12.29 tag v1.12.29 (2d90d6b7b601ecb9ccdf81239a43b4396b4b0c9e). Gated: Univention banner + ICS.
AuthICS operator / ICS compromise. Victim is a signed-in user who clicks the menu item.
LicenseGNU Affero GPL v3.0
Lab127.0.0.1 only

What an attacker can do

Compromise or operate the ICS that the Element deploy trusts. Put a javascript: (or data:) URL in navigation.json. Wait for a signed-in user to open the banner menu and click the item. That is Matrix account takeover: access token, crypto store, the session. It is not OS RCE. Desktop still has nodeIntegration off and a sandbox.

PrivilegeMethod / sinkRecon / integrity / availabilityLab-proven or inferred
Render a banner-menu <a href="javascript:…"> on the Element originICS navigation.json entries[].link -> navigationToConfig link_url -> Menu.tsx LinkButton href={link.link_url}Integrity of the menu DOMLab-proven. Mock ICS link javascript:ELEMENT-ICS-JAVASCRIPT-WITNESS became that href. https portal link still rendered
Run script as the Element origin after a clickVictim clicks the menu item (UI:R)IntegrityInferred from the href sink. Lab did not drive a browser click or steal a live Matrix token
Read the Matrix access token / crypto store (account takeover)In-origin script vs localStorage / IndexedDB sessionRecon / integrityInferred from Element origin XSS. Lab witness is the href string
Top-navigate the Element tab to a phishing pageSilentLogin.tsx unsandboxed iframe src={new URL("silent", icsUrl)}IntegrityLab-proven the iframe has no sandbox. Top-navigation not exercised
Same plant via data:z.string() accepts any schemeIntegrityInferred. Lab planted javascript: only

Closed on this pin: default app.element.io (no Univention banner). OS RCE / LPE (Desktop nodeIntegration: false, sandbox, contextIsolation). Timeline HTML XSS. URL-preview javascript: (GHSA-9r5h previewFromBundle requires http:/https:). HTML export XSS (GHSA-wqmv). Widget media token (GHSA-3jm3). Static banner link_url: z.url() is operator config, not ICS; z.url() is also not an http/https allowlist.

Same pin leftovers: fragment guest wipe, vector: Windows drive-letter.

How I found it

I pinned Element Web v1.12.29 after the 22 Sep 2026 GitHub release. URL preview already learned http:/https: the hard way. Univention ICS link is still z.string(). Static menu config uses z.url(). The fetch path never goes through that check.

Wrong turns already recorded: treating default app.element.io as the victim (Univention is gated); treating z.url() as a scheme allowlist (the URL constructor accepts javascript:); inflating click XSS to OS RCE. A reverse shell. Theatre.

Lab

Gadget of the pin functions plus a mock ICS navigation.json. Not a live Element Web container. how=gadget. Applying the URL-preview http/https allowlist (previewFromBundle) dropped the javascript href and kept the https portal link.

python3 element-ics-javascript-Abraxas-Labs.py

or

cd lab
./run.sh

Target only http://127.0.0.1:19620. Compose project element-ics-javascript. Stack tears down after the run.

SUCCESS element-ics-javascript how=gadget href-scheme=javascript menu-a-javascript=yes allowlist-rejects=yes silent-no-sandbox=yes ELEMENT-ICS-JAVASCRIPT-WITNESS

The fix

Allowlist http: and https: on ICS link the same way previewFromBundle does. Reject javascript:, data:, and other schemes before href=. Sandbox the silent iframe (sandbox="" or at least no allow-top-navigation). Do not treat z.url() as a scheme allowlist.

References

  • github.com/element-hq/element-web tag v1.12.29
  • navigation.ts
  • Menu.tsx
  • SilentLogin.tsx
  • Nearby patched (not this href): GHSA-9r5h previewFromBundle
  • Same pin: element-fragment-guest · element-vector-drive-letter
  • CWE-79

License

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

Download Tool