CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-24128
Critical (Vendor Assessment)

Log, Stock, and Barrel: XSS in XWiki's Logging Macros

Alon Barad
Alon Barad
Software Engineer

Jan 23, 2026·6 min read·18 visits

PoC Available

Executive Summary (TL;DR)

XWiki Platform trusted user input a little too much in its `logging_macros.vm` template. By supplying a malicious extension ID during an installation request, an attacker can poison the logs. When an admin views these logs to debug the failure, the script executes, potentially leading to session hijacking. Fixed in versions 16.10.12, 17.4.5, and 17.8.0-rc-1.

A reflected Cross-Site Scripting (XSS) vulnerability in the XWiki Platform's logging infrastructure allows attackers to inject malicious scripts via crafted extension identifiers, targeting administrators viewing system logs.

The Hook: Velocity and the Art of Blind Trust

XWiki is a beast. It's a second-generation wiki engine written in Java, but its frontend logic relies heavily on Velocity templates. For those uninitiated in the ancient arts of Java templating, Velocity is powerful. It lets you mix logic with HTML generation seamlessly. But as with all powerful tools, it assumes you know what you are doing. If you hand it raw data, it prints raw data.

In the grand tapestry of a complex application, logging is usually the boring part. It's the janitor of the codebase—quietly cleaning up errors and storing them for later. Nobody expects the janitor to stab them in the back.

However, in XWiki, logs aren't just text files in /var/log. They are rich, interactive elements presented in the UI. When you try to install an extension, the system logs the progress. If it fails, it logs the error. And if the error contains user input that hasn't been scrubbed, the UI doesn't just display the error—it runs it. CVE-2026-24128 is exactly that: a case where the system tried to be helpful by hyperlinking an extension ID, only to accidentally turn a typo into a tactical nuke.

The Flaw: When IDs Attack

The vulnerability lives in xwiki-platform-core/xwiki-platform-web/xwiki-platform-web-templates/src/main/resources/templates/logging_macros.vm. This template is responsible for making log messages look pretty in the browser. Specifically, it handles messages related to the Extension Manager—the part of XWiki that installs plugins and themes.

The logic seems innocent enough: if a log message involves an extension ID, turn that ID into a clickable link so the user can easily visit the extension's homepage. The developers assumed that an Extension ID would be a safe string—maybe something like org.xwiki.platform:xwiki-platform-web.

But assumptions are the mother of all security advisories. The code didn't check if the ID was actually an ID. It simply took the $argument variable (holding the ID) and shoved it directly into the anchor tag's text content. It's the classic "Reflected XSS via Error Message" pattern. You ask the server for something that doesn't exist, and the server helpful echoes back: "I couldn't find [YOUR_MALICIOUS_PAYLOAD] for you."

Because Velocity in this context does not auto-escape variables placed inside string literals or assignments unless explicitly told to, the browser receives the raw payload. If that payload is <script>alert(1)</script>, the browser obeys.

The Code: The Smoking Gun

Let's look at the crime scene. The vulnerable code was inside a macro used to format log arguments. Here is the simplified logic before the fix:

 

Vulnerable Code in logging_macros.vm

#if ($argument.id) #set ($version = $argument.versionConstraint)

Generating the URL is fine...

#set ($_extensionURL = "#getExtensionURL($argument.id, $version)")

...but THIS is where the wheels fall off.

#set ($_extensionName = $argument) #end

The variable is interpolated directly into HTML

#set ($message = "$message<a href=""$_extensionURL"" class=""extension-link"">$_extensionName</a>")


The variable `$_extensionName` is assigned the raw `$argument` object (which toString()s to the attacker's input). It is then placed between the `<a>` tags.

The fix is elegantly simple. XWiki developers introduced the standard XML escape tool. This converts `<` to `&lt;` and `>` to `&gt;`, neutering any HTML tags.

```diff
- #set ($_extensionName = $argument)
+ #set ($_extensionName = $!escapetool.xml($argument))

By wrapping the argument in $!escapetool.xml(), the browser renders the malicious string as harmless text rather than executing it. It's a one-line change that closes a massive window of opportunity.

The Exploit: Poisoning the Well

So, how do we weaponize this? We need to trigger a log event that contains our payload. The Distribution Wizard or the Extension Manager are perfect candidates. These components take an Extension ID as input to look up packages.

Here is the attack chain:

  1. Recon: The attacker identifies the URL endpoint used to search for or resolve extensions. This is often accessible to users with low privileges or can be triggered via CSRF if not properly protected.
  2. The Bait: The attacker constructs a URL that initiates an extension resolution for a non-existent, maliciously named extension.
    • Payload: org.xwiki:fake<img src=x onerror=alert(document.cookie)>
  3. The Trigger: The XWiki backend attempts to find this extension. It fails (obviously), and generates a log entry: "Failed to resolve extension [PAYLOAD]".
  4. The Trap: The administrator, wondering why their installation is failing, navigates to the Job Status or Log View page. The page loads logging_macros.vm to render the error.
  5. Execution: The macro runs, the payload is injected into the DOM, and the JavaScript executes in the context of the administrator's session.

This is a "stored-reflected" scenario: the payload is reflected from the immediate request log, or transiently stored in the job status log, waiting for the victim to look at it.

The Impact: Why Should We Panic?

Why is this critical? It's just XSS, right? In the context of a Wiki, XSS is often game over. XWiki isn't just a blog; it's an enterprise knowledge management system. It often holds proprietary data, internal documentation, and sometimes credentials.

If an attacker can execute JavaScript in the context of an XWiki administrator:

  1. Account Takeover: They can steal the JSESSIONID or other authentication tokens.
  2. RCE Escalation: XWiki has powerful scripting capabilities (Groovy, Python, Velocity) accessible to admins. An attacker with admin access can easily elevate XSS to Remote Code Execution (RCE) by saving a page containing a Groovy script and executing it.
  3. Wormability: The script could programmatically modify other wiki pages to inject the XSS payload permanently, creating a self-propagating worm inside the internal network.

This isn't just popping an alert box; it's handing over the keys to the castle.

The Fix: Closing the Window

If you are running XWiki, stop reading and start patching. The vulnerability is fixed in XWiki Platform versions 16.10.12, 17.4.5, and 17.8.0-rc-1.

If you cannot upgrade immediately, you have very few good options. You could attempt to manually patch the logging_macros.vm file if you have filesystem access to the server, but modifying core templates is risky and gets overwritten during updates.

Defensive In-Depth:

  • Content Security Policy (CSP): Implement a strict CSP that disallows inline scripts (script-src 'self'). This kills the majority of XSS vectors, although it requires careful tuning for a dynamic platform like XWiki.
  • WAF Rules: Configure your WAF to block requests containing HTML tags in query parameters, specifically targeting patterns like %3Cscript or %3Cimg sent to /bin/view/XWiki/DistributionWizard.

Official Patches

XWikiCommit fixing the vulnerability in logging_macros.vm

Fix Analysis (1)

Technical Appendix

CVSS Score
Critical (Vendor Assessment)/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H

Affected Systems

XWiki Platform

Affected Versions Detail

Product
Affected Versions
Fixed Version
XWiki Platform
XWiki
>= 7.0-milestone-2, < 16.10.1216.10.12
XWiki Platform
XWiki
>= 17.0, < 17.4.517.4.5
XWiki Platform
XWiki
>= 17.5, < 17.8.0-rc-117.8.0-rc-1
AttributeDetail
CWE IDCWE-79
Attack VectorNetwork
CVSS ScoreCritical (Vendor Internal)
ImpactSession Hijacking / Potential RCE
Exploit StatusPoC Available (Theoretical)
KEV StatusNot Listed

MITRE ATT&CK Mapping

T1190Exploit Public-Facing Application
Initial Access
T1059.007Command and Scripting Interpreter: JavaScript
Execution
T1552Unsecured Credentials
Credential Access
CWE-79
Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')

The software does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.

Known Exploits & Detection

Manual AnalysisExploit involves passing HTML tags in extension ID parameters.

Vulnerability Timeline

Fix committed to GitHub
2025-09-12
Public Disclosure
2026-01-01

References & Sources

  • [1]XWiki Jira Ticket XWIKI-23462
  • [2]XWiki Platform GitHub Repository

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.