Feb 22, 2026·7 min read·57 visits
The XWiki Full Calendar Macro (< 2.4.5) contains a trivial HQL injection. Attackers can pass a full database query via the URL parameters, executing it with the privileges of the script author (often Admin). This grants read access to all data, including credentials.
A 10.0 Critical vulnerability in the XWiki Full Calendar Macro allows unauthenticated attackers to execute arbitrary Hibernate Query Language (HQL) commands. By manipulating the 'sql', 'fromsql', or 'wheresql' parameters in the Calendar.JSONService page, attackers can bypass security controls, exfiltrate the entire wiki database, or potentially deny service to the host. The flaw stems from direct concatenation of user input into database queries, essentially providing a remote database shell to anyone who asks nicely.
We often ignore the little things. The plugins, the macros, the 'quality of life' add-ons that make enterprise software bearable. In the XWiki ecosystem, the Full Calendar Macro is one such tool—a simple utility to display events. But as with many innocent-looking features, it harbored a dark secret. It didn't just display events; it acted as an open gateway to the underlying database.
This vulnerability, tracked as CVE-2025-65091, is a perfect example of what happens when convenience overrides security. It isn't a complex memory corruption bug or a subtle race condition. It is a logic flaw so glaring that it feels almost polite. The application essentially asked the user, "Hey, what database query would you like me to run for you today?" and then dutifully executed it.
Because XWiki relies heavily on HQL (Hibernate Query Language), this isn't just about reading calendar entries. An injection here allows an attacker to traverse the object graph, accessing user profiles, password hashes (if stored), and proprietary documentation. Worse, it was exploitable by unauthenticated users, earning it the rare and terrifying CVSS 10.0 score. If you had this macro installed, your wiki was effectively public.
The root cause of this vulnerability lies in the file Calendar.JSONService.xml. This script is responsible for fetching event data to populate the calendar UI. To do this, it constructs a database query. In a secure application, this would be done using a fixed query with parameterized inputs. In the vulnerable version, it was done using string concatenation of the worst kind.
The developers implemented a feature that allowed the frontend to specify exactly how to filter data. They exposed parameters like request.sql, request.fromsql, and request.wheresql. If the sql parameter was present, the code would simply take that string and treat it as the entire HQL query.
Think about that for a second. The code explicitly checked: "Did the user provide a full SQL command? If yes, let's run that instead of our logic." It is the web application equivalent of leaving the keys in the ignition with the engine running and a sign on the dashboard that says "Free Car."
Even if the sql parameter wasn't used, the code blindly concatenated fromsql and wheresql into the query string. This meant that even without replacing the whole query, an attacker could inject JOIN statements to link sensitive tables or modify the WHERE clause to bypass visibility checks. It is a textbook Injection flaw, mapped to CWE-89, but operating at the ORM level.
Let's look at the vulnerable Velocity code. This is where the magic (and the horror) happens.
The Vulnerable Code (Pre-Patch):
#if ("$!\{request.sql\}" != '')
## The developer trusts the user implicitly here.
#set ($hql = $request.sql)
#else
## Even the fallback is dangerous.
#set ($hql =", BaseObject as obj $!\{request.fromsql\} where doc.fullName=obj.name and obj.className='$\{request.classname\}' $!\{request.wheresql\}")
#end
...#foreach ($item in $services.query.hql($hql).execute())
The variable `$request.sql` is taken directly from the URL query string. If I send `?sql=select...`, the variable `$hql` becomes my query. The `$services.query.hql($hql).execute()` line then runs it against the database.
**The Fix (Version 2.4.5):**
The developers stripped out the direct override and added a critical permission drop.
```velocity
#set ($hqlStatement =", BaseObject as obj $!{request.fromsql} where doc.fullName=obj.name and obj.className=:classname $!{request.wheresql}") ...
#set ($discard = $xcontext.dropPermissions())
#foreach ($item in $services.query.hql($hqlStatement).bindValue("classname", "$!{request.classname}").addFilter('currentlanguage').execute())
Notice two things: First, the ability to completely replace the query via `sql` is gone. Second, and arguably more importantly, `$xcontext.dropPermissions()` is called. In XWiki, scripts often run with the permissions of the *author* (usually an Admin who installed the extension). `dropPermissions()` forces the script to run with the permissions of the *requestor*. If you are an unauthenticated attacker, you are now just "Guest," and you can't query sensitive tables even if you manage to inject SQL.
Exploiting this is trivially easy. You don't need Burp Suite; you just need a web browser. The attack vector targets the JSONService which is publicly accessible.
Scenario 1: The Full Dump
An attacker wants to list all documents in the wiki to map out the internal structure.
URL:
http://target-wiki/xwiki/bin/view/Calendar/JSONService?sql=select+doc.fullName,+doc.title+from+XWikiDocument+doc
The server sees the sql parameter, ignores its internal logic, and executes the HQL: select doc.fullName, doc.title from XWikiDocument doc. The JSON response will kindly return every document title in the system.
Scenario 2: Credential Hunting
XWiki stores user data in objects. While password hashes might be salted, getting the list of usernames and their metadata is a goldmine for social engineering or brute force.
URL:
http://target-wiki/xwiki/bin/view/Calendar/JSONService?sql=select+obj.name+from+BaseObject+obj+where+obj.className='XWiki.XWikiUsers'
Scenario 3: The 'Re-Exploit' (Post-Patch Bypass Attempt)
Look closely at the patched code. The developer still includes $!{request.fromsql} and $!{request.wheresql} in the query string!
#set ($hqlStatement =", BaseObject as obj $!{request.fromsql} ... $!{request.wheresql}")While they bound :classname and removed request.sql, injection is technically still possible in the FROM and WHERE clauses. However, because of $xcontext.dropPermissions(), the query runs as 'Guest'. So, while I can still inject HQL syntax (e.g., ?fromsql=, XWikiDocument as doc), I can only retrieve data that 'Guest' is allowed to see. The exploit is neutered not by fixing the injection fully, but by stripping the privileges required to make the injection dangerous. It's a functional fix, but a dirty one from a code purity standpoint.
A CVSS score of 10.0 is reserved for the absolute worst-case scenarios. Why did a calendar plugin merit this?
sql could lock up the database, causing a Denial of Service.Essentially, this flaw turns a collaboration tool into a data exfiltration pipe. For organizations using XWiki as an internal knowledge base, this exposes everything from network diagrams to HR policies to the public internet.
If you are running org.xwiki.contrib:macro-fullcalendar versions older than 2.4.5, you are vulnerable. The remediation is straightforward: Update the extension immediately.
If you cannot update for some reason (perhaps you've forked the code), you must manually patch Calendar.JSONService.xml. The most critical change is ensuring that the script drops permissions before executing any query that touches user input.
Remediation Checklist:
macro-fullcalendar to 2.4.5+ via the Extension Manager.Calendar.JSONService source code for $xcontext.dropPermissions().JSONService containing query parameters like select, from, or join. If you see these, you have likely already been scanned or compromised.Since this exploit leaves no binary artifacts (it's just a web request), log analysis is your only hope for forensic confirmation.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
macro-fullcalendar XWiki Contrib | < 2.4.5 | 2.4.5 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-89 (SQL Injection) |
| CVSS v3.1 | 10.0 (Critical) |
| Attack Vector | Network (HQL Injection via GET parameters) |
| Exploit Status | PoC Available / Trivial |
| Privileges | None (Unauthenticated) |
| Patch Commit | 5fdcf06a05015786492fda69b4d9dea5460cc994 |
An uncontrolled resource consumption vulnerability exists in the Scala-based http4s-blaze-server package of the http4s/blaze library. The vulnerability allows remote, unauthenticated attackers to cause an Out of Memory Error (OOM) and JVM crash by streaming a continuous sequence of small or empty WebSocket continuation frames with the FIN bit set to 0. This bypasses typical payload size checks because of the JVM's per-object allocation overhead, leading to rapid heap exhaustion with minimal network bandwidth.
A critical path traversal vulnerability has been identified in the OpenList Go-based backend package. The vulnerability exists within the batch rename handler because the application does not validate the source filename parameter before constructing filesystems paths. This omission allows authenticated users to escape their designated directory and rename files in sibling paths.
OpenList version 4.2.3 and prior is vulnerable to an authorization bypass and metadata leakage. When configured with the Bleve search engine backend, OpenList fails to perform separator-aware path matching when validating tenant containment. This allows authenticated users to access sibling directories sharing similar name prefixes. Furthermore, the search backend returns unfiltered global result counts, leaking existence verification data of unauthorized files via side-channel analysis.
An authorization bypass vulnerability in OpenList version 4.2.3 and below allows authenticated users to read arbitrary files outside of their designated base directories due to an insecure path prefix check using Go's standard strings.HasPrefix function.
A security policy bypass vulnerability exists in the AWS API MCP Server (awslabs-aws-api-mcp-server) from version 0.2.13 through 1.3.46. When the server fails to load the read-only operations index during startup (due to transient network failures, file permission issues, or other exceptions), it logs a warning but continues running in an insecure, degraded state. Under this condition, the security policy engine fails open, silently skipping all subsequent security checks and consent prompts for the lifetime of the process. This permits unauthorized mutating AWS CLI commands to execute via indirect prompt injection attacks.
An incomplete escaping vulnerability in the npm package 'shescape' allows unauthenticated users to trigger dynamic shell expansions, absolute path disclosure, and command block break-outs on Unix and Windows systems.