📄 OpenClaw Dashboard Cross Site Scripting
| Reporter | Title | Published | Views | Family All 8 |
|---|---|---|---|---|
| CVE-2026-66421 | 30 Jul 202622:16 | – | attackerkb | |
| CVE-2026-66421 | 30 Jul 202623:00 | – | circl | |
| CVE-2026-66421 | 30 Jul 202622:16 | – | cve | |
| CVE-2026-66421 OpenClaw Dashboard Stored XSS via lastMessage Session Field | 30 Jul 202622:16 | – | cvelist | |
| EUVD-2026-51337 | 31 Jul 202600:30 | – | euvd | |
| CVE-2026-66421 | 30 Jul 202623:16 | – | nvd | |
| PT-2026-66628 | 30 Jul 202600:00 | – | ptsecurity | |
| CVE-2026-66421 OpenClaw Dashboard Stored XSS via lastMessage Session Field | 30 Jul 202622:16 | – | vulnrichment |
# Security Advisory: Stored Cross-Site Scripting Via Agent Messages Leading To Session Token Theft (openclaw-dashboard)
Title: OpenClaw Dashboard Stored XSS via lastMessage Session Field
CVE ID: CVE-2026-66421
https://github.com/tugcantopaloglu/openclaw-dashboard
## Summary
The sessions table on the dashboard's landing page shows the last message of each agent
session. That text is taken from the agent's conversation transcript and written into
the page with `innerHTML` and no escaping. OpenClaw is a multi-channel agent gateway, so
the message text can come from anyone who is able to talk to the agent, such as a chat
group or a webhook. A message containing an HTML payload runs as script in the
administrator's browser as soon as they open the dashboard.
- CWE-79: Improper Neutralization of Input During Web Page Generation (Cross-site Scripting)
- CVSS 4.0: 8.8 (High). Vector: `CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:H/VI:H/VA:N/SC:H/SI:H/SA:N`
## Affected versions
Present since the first public release. The vulnerable render exists in the earliest
tag (v1.1.0) and in every later commit up to and including the current `main`
(d6198d0). Not fixed at the time of writing.
## Threat model
The attacker is a party who can send a message that lands in the agent's session
transcript. They do not need a dashboard account. In a typical OpenClaw deployment this
includes members of connected chat channels and any source that reaches the agent
through a webhook, so the attacker is often outside the operator's trust boundary.
The payload is stored in the transcript and rendered whenever the administrator views
the sessions page. That page is the default landing view and refreshes on a timer, so
the only interaction required is the administrator loading the dashboard they normally
use. `AT:P` reflects the one condition the attacker relies on: that the deployment
routes their messages into a session the dashboard displays.
## Root cause
**Step 1. The message text is extracted from the transcript.** The server reads the
most recent message and returns its text, cut to 80 characters, with no sanitization:
```js
// server.js:474-481
if (typeof msg.content === 'string') {
text = msg.content;
} else if (Array.isArray(msg.content)) {
for (const b of msg.content) {
if (b.type === 'text' && b.text) { text = b.text; break; }
}
}
if (text) return text.replace(/\n/g, ' ').substring(0, 80);
```
**Step 2. It is exposed through the sessions API.** `getSessionsJson` puts the text on
the `lastMessage` field of each session:
```js
// server.js:538
lastMessage: getLastMessage(s.sessionId || key),
```
`GET /api/sessions` returns this array to the browser.
**Step 3. It is written into the DOM without escaping.** The sessions table builds each
row by string concatenation and assigns it with `innerHTML`:
```js
// index.html:3758
const lastMsg = s.lastMessage ? s.lastMessage.substring(0, 60) + (s.lastMessage.length > 60 ? '…' : '') : '';
```
```js
// index.html:3773
<div class="table-cell" style="..." onclick="toggleSessionExpand('${escapedKey}', event)">${lastMsg}</div>
```
`lastMsg` is placed straight into the HTML string. There is no encoding step anywhere on
this path.
The same table interpolates `s.label` (index.html:3770) and `s.key` (index.html:3767)
into the row markup the same way. Those fields have no 60-character cap, so they give an
attacker who can influence them more room for a payload.
The Content-Security-Policy at server.js:298 allows inline event handlers
(`script-src 'self' 'unsafe-inline'`), so an `onerror` handler runs.
## Proof of concept
1. As a party who can message the agent, send a message whose text is a short payload
that fits the 60-character budget, for example:
```
<img src=x onerror=console.log('xss',getStoredToken())>
```
This is 56 characters and reaches the agent's session transcript like any normal
message.
2. Confirm the server hands the payload back unescaped:
```bash
curl -H "Authorization: Bearer ADMIN_TOKEN" http://TARGET:7000/api/sessions
```
The affected session's `lastMessage` field contains the raw `<img ...>` string.
3. The administrator opens the dashboard. The sessions page is the default view, so no
extra navigation is needed. The row renders, the browser parses the `<img>` tag, the
`onerror` handler runs, and the administrator's session token is read by the payload.
Replacing the `console.log` body with a `fetch` to a same-origin authenticated endpoint lets the payload act
with the logged in user's privileges.
## Impact
Script execution in the dashboard origin as the logged in user, reachable by someone who
only needs to send the agent a message. The payload can read the session token and call
authenticated endpoints, including those that edit the agent's own instruction files and
the OpenClaw configuration. Because it fires on the default page, the administrator does
not have to take any unusual action.
## Remediation
- HTML-encode `lastMessage`, `label`, and `key` before inserting them into the row
markup, or construct the cells with `textContent` rather than an HTML string.
- Apply the same encoding to the other session fields rendered through `innerHTML`.
- Remove `'unsafe-inline'` from `script-src` so injected markup cannot execute even if an
encoding step is missed.Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation
03 Aug 2026 00:00Current
4.8Medium risk
Vulners AI Score4.8
CVSS 48.8
CVSS 3.19.3
EPSS0.00363
SSVC